fix(updates): resolve component update hang and multiple page reload loop

- action.uc: sweep stuck flock 1000 processes before tachyon restart, bound service restart with 25s timeout, and prevent worker lockup
- shell/index.ts: add 15-minute general hard timeout for non-Tachyon components to prevent infinite modal spin; allow same-version confirmation for both install and reinstall
- package.uc: remove disruptive uhttpd restart from luci_postinst to prevent active socket drops
- ui.uc: refresh stale PID state before checking value.running in action_ack so dead jobs can always be acknowledged
- initController.ts & sessionJobs.ts: persist handled job IDs across reloads in sessionStorage, eliminate redundant modal popups on page reload, and guard against concurrent reloads with safeReloadPage
- renderUpdateProgressModal.ts: record active job before reload and poll readiness with fast health check instead of blind 5s freeze
This commit is contained in:
Dushnilin
2026-09-03 07:36:30 +03:00
parent 36fe7ef312
commit abaa891dd3
12 changed files with 417 additions and 119 deletions
+40 -1
View File
@@ -447,6 +447,42 @@ function command_output_from_args(args) {
return command_output(command_from_args(args) + " 2>/dev/null");
}
let timeout_prefix_cache = null;
function timeout_prefix() {
if (timeout_prefix_cache != null)
return timeout_prefix_cache;
if (command_status("timeout 1 /bin/true >/dev/null 2>&1") == 0)
timeout_prefix_cache = [ "timeout" ];
else if (command_status("timeout -t 1 /bin/true >/dev/null 2>&1") == 0)
timeout_prefix_cache = [ "timeout", "-t" ];
else
timeout_prefix_cache = [];
return timeout_prefix_cache;
}
function bounded_command(command, seconds) {
seconds = as_string(seconds || "30");
let prefix = timeout_prefix();
if (length(prefix) == 0)
return as_string(command);
return join(" ", prefix) + " " + seconds + " " + as_string(command);
}
function kill_matching_command(grep_args) {
return "__anc=\" \"; __p=$$; " +
"while [ -n \"$__p\" ] && [ \"$__p\" -gt 1 ] 2>/dev/null; do " +
"__anc=\"$__anc$__p \"; " +
"__p=$(awk '{ sub(/.*\\) /, \"\"); print $2 }' \"/proc/$__p/stat\" 2>/dev/null); " +
"done; " +
"ps 2>/dev/null | grep " + grep_args + " | grep -v grep | grep -v -E 'action[.]uc|updates[.]uc' | awk '{print $1}' | " +
"while read _pid; do case \"$__anc\" in *\" $_pid \"*) continue;; esac; " +
"kill -9 \"$_pid\" 2>/dev/null; done; true";
}
function ensure_dir(path) {
path = as_string(path);
if (path == "") return false;
@@ -559,5 +595,8 @@ return {
write_file,
file_exists,
parent_dir,
get_mixed_port
get_mixed_port,
timeout_prefix,
bounded_command,
kill_matching_command
};