diff --git a/repos/gems/src/app/depot_download_manager/gen_fetchurl.cc b/repos/gems/src/app/depot_download_manager/gen_fetchurl.cc index fc9edd1186..a60a73e3e9 100644 --- a/repos/gems/src/app/depot_download_manager/gen_fetchurl.cc +++ b/repos/gems/src/app/depot_download_manager/gen_fetchurl.cc @@ -18,10 +18,11 @@ void Depot_download_manager::gen_fetchurl_start_content(Xml_generator &xml, Url const ¤t_user_url, Fetchurl_version version) { + xml.attribute("version", version.value); + gen_common_start_content(xml, "fetchurl", Cap_quota{500}, Ram_quota{8*1024*1024}); - xml.attribute("version", version.value); xml.node("config", [&] () { xml.node("libc", [&] () { xml.attribute("stdout", "/dev/log"); diff --git a/repos/gems/src/app/depot_download_manager/main.cc b/repos/gems/src/app/depot_download_manager/main.cc index 702d1a5d34..fde31cd620 100644 --- a/repos/gems/src/app/depot_download_manager/main.cc +++ b/repos/gems/src/app/depot_download_manager/main.cc @@ -16,6 +16,7 @@ #include #include #include +#include /* local includes */ #include "xml.h" @@ -195,10 +196,18 @@ struct Depot_download_manager::Main : Import::Download_progress Signal_handler
_fetchurl_progress_handler { _env.ep(), *this, &Main::_handle_fetchurl_progress }; + /* number of bytes downloaded by current fetchurl instance */ + uint64_t _downloaded_bytes { }; + void _handle_fetchurl_progress() { _fetchurl_progress.update(); + /* count sum of bytes downloaded by current fetchurl instance */ + _downloaded_bytes = 0; + _fetchurl_progress.xml().for_each_sub_node("fetch", [&] (Xml_node fetch) { + _downloaded_bytes += fetch.attribute_value("now", 0ULL); }); + if (_import.constructed()) { _import->apply_download_progress(*this); @@ -210,6 +219,42 @@ struct Depot_download_manager::Main : Import::Download_progress _update_state_report(); } + struct Fetchurl_watchdog + { + Main &_main; + + Timer::Connection _timer { _main._env }; + + Signal_handler _handler { + _main._env.ep(), *this, &Fetchurl_watchdog::_handle }; + + uint64_t _observed_downloaded_bytes = _main._downloaded_bytes; + + void _handle() + { + if (_main._downloaded_bytes != _observed_downloaded_bytes) { + _observed_downloaded_bytes = _main._downloaded_bytes; + return; + } + + warning("fetchurl got stuck, respawning"); + + /* downloads got stuck, try replacing fetchurl with new instance */ + _main._fetchurl_count.value++; + _main._generate_init_config(); + } + + enum { PERIOD_SECONDS = 5UL }; + + Fetchurl_watchdog(Main &main) : _main(main) + { + _timer.sigh(_handler); + _timer.trigger_periodic(PERIOD_SECONDS*1000*1000); + } + }; + + Constructible _fetchurl_watchdog { }; + Main(Env &env) : _env(env) { _dependencies .sigh(_query_result_handler); @@ -269,7 +314,9 @@ void Depot_download_manager::Main::_generate_init_config(Xml_generator &xml) gen_depot_query_start_content(xml, _installation.xml(), _next_user, _depot_query_count, _jobs); }); - if (_import.constructed() && _import->downloads_in_progress()) { + bool const fetchurl_running = _import.constructed() + && _import->downloads_in_progress(); + if (fetchurl_running) { try { xml.node("start", [&] () { gen_fetchurl_start_content(xml, *_import, _current_user_url(), @@ -293,6 +340,8 @@ void Depot_download_manager::Main::_generate_init_config(Xml_generator &xml) gen_extract_start_content(xml, *_import, _current_user_path(), _current_user_name()); }); } + + _fetchurl_watchdog.conditional(fetchurl_running, *this); }