fix(stability): optimize Go memory tiers, prevent nftables degradation deadlock, harden NTP & process supervision
- singbox/runtime.uc: add dynamic 4-tier GOMEMLIMIT and GOGC limits based on RAM, enforce /etc/tachyon/mem_scale, and install managed init script across all binary variants - service/event_controller.uc: guard probe_nftables() with recovery_bypass and native_internet_restored checks to prevent 5-minute network drop deadlock - service/watchdog.uc: reduce Telegram worker heartbeat timeout from 900s to 300s and add nslookup fallback to Zero-RTT prefetcher - diagnostics/runtime.uc & service/lifecycle.uc: use direct-IP NTP pool to eliminate circular DNS/TLS deadlocks, and step clock forward on cold boot if RTC desynced - service/failover.uc & diagnostics/runtime.uc: flush conntrack states on proxy group switch so client connections immediately migrate
This commit is contained in:
@@ -1864,6 +1864,8 @@ function clash_api(action, arg1, arg2, arg3) {
|
||||
push(args, "--data-raw");
|
||||
push(args, payload);
|
||||
let result = status_capture([ "clash-set-group-proxy-result", arg1, arg2 ], command_output(command_from_args(args)));
|
||||
if (result.status == 0)
|
||||
command_status("conntrack -F >/dev/null 2>&1 || true");
|
||||
if (result.output != "")
|
||||
print(result.output);
|
||||
return result.status;
|
||||
@@ -3930,7 +3932,7 @@ function apply_quick_fix(codes_str) {
|
||||
status = (rc == 0);
|
||||
msg = status ? "Tachyon stopped, stock dnsmasq and native direct internet routing restored" : "Native internet restore failed (exit " + rc + ")";
|
||||
} else if (c == "fix_system_time") {
|
||||
let rc = command_status("ntpd -q -p pool.ntp.org 2>/dev/null || rdate -s time.cloudflare.com 2>/dev/null; /etc/init.d/sysntpd restart 2>/dev/null");
|
||||
let rc = command_status("ntpd -q -p 194.190.168.1 -p 216.239.35.0 -p 162.159.200.1 2>/dev/null || ntpd -q -p pool.ntp.org 2>/dev/null || rdate -s time.cloudflare.com 2>/dev/null; /etc/init.d/sysntpd restart 2>/dev/null");
|
||||
status = (rc == 0);
|
||||
msg = status ? "System time synchronized with NTP" : "NTP sync failed (exit " + rc + ")";
|
||||
} else if (c == "flush_conntrack") {
|
||||
|
||||
@@ -642,6 +642,8 @@ function controller(bus, opts) {
|
||||
|
||||
// ── Probe: nftables table and QoS marks ───────────────────────────────────
|
||||
function probe_nftables() {
|
||||
if (setting("recovery_bypass", "0") == "1") return;
|
||||
if (fs.stat("/var/run/tachyon/native_internet_restored") != null) return;
|
||||
if (is_list_update_running()) return;
|
||||
if (is_reload_in_progress()) return;
|
||||
|
||||
@@ -666,6 +668,7 @@ function controller(bus, opts) {
|
||||
// ── Probe: TPROXY port liveness ───────────────────────────────────────────
|
||||
function probe_tproxy() {
|
||||
if (setting("recovery_bypass", "0") == "1") return;
|
||||
if (fs.stat("/var/run/tachyon/native_internet_restored") != null) return;
|
||||
if (is_reload_in_progress()) return;
|
||||
|
||||
let pid = get_sing_box_pid();
|
||||
|
||||
@@ -121,6 +121,7 @@ function switch_group(section_name, outbound_name) {
|
||||
log_message("runtime switch failed: " + out, "warn");
|
||||
return false;
|
||||
}
|
||||
command_status("conntrack -F >/dev/null 2>&1 || true");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -835,6 +835,11 @@ function start_impl() {
|
||||
if (wd_status != 0)
|
||||
log_message("Watchdog start-runtime failed (status " + as_string(wd_status) + ")", "warn");
|
||||
|
||||
if (time() < 1704067200) {
|
||||
log_message("System clock is in the past (RTC desync); performing quick NTP synchronization...", "warn");
|
||||
command_status("ntpd -q -p 194.190.168.1 -p 216.239.35.0 -p 162.159.200.1 >/dev/null 2>&1 || true");
|
||||
}
|
||||
|
||||
let status = start_main();
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
@@ -349,7 +349,7 @@ function run_zero_rtt_prefetching() {
|
||||
// that followed it attached to a null command in this shell instead
|
||||
// of to the backgrounded loop. Backgrounding is now the wrapper's
|
||||
// job, so the loop gets the redirections it was always meant to have.
|
||||
let batch_cmd = "for d in " + join(" ", batch) + "; do dig @127.0.0.1 \"$d\" A >/dev/null 2>&1; done";
|
||||
let batch_cmd = "for d in " + join(" ", batch) + "; do dig @127.0.0.1 \"$d\" A >/dev/null 2>&1 || nslookup \"$d\" 127.0.0.1 >/dev/null 2>&1; done";
|
||||
system(common.background_command(batch_cmd));
|
||||
batch = [];
|
||||
}
|
||||
@@ -1976,7 +1976,7 @@ function check_telegram_worker() {
|
||||
}
|
||||
|
||||
let age = time() - int(heartbeat);
|
||||
if (age <= 900)
|
||||
if (age <= 300)
|
||||
return;
|
||||
|
||||
let pid = trim(fs.readfile(TELEGRAM_PID_FILE) || "");
|
||||
|
||||
@@ -369,7 +369,7 @@ function owner_pid() {
|
||||
|
||||
function managed_service_installed() {
|
||||
let data = fs.readfile("/etc/init.d/sing-box");
|
||||
return data != null && index(as_string(data), SB_MANAGED_SERVICE_MARKER) >= 0;
|
||||
return data != null && index(as_string(data), SB_MANAGED_SERVICE_MARKER) >= 0 && index(as_string(data), "GOGC") >= 0;
|
||||
}
|
||||
|
||||
function managed_service_text() {
|
||||
@@ -381,7 +381,7 @@ function managed_service_text() {
|
||||
"start_service() {\n" +
|
||||
" config_load \"sing-box\"\n" +
|
||||
" local enabled config_file working_directory\n" +
|
||||
" local log_stderr mem_total_kb mem_limit_mb\n\n" +
|
||||
" local log_stderr mem_total_kb mem_limit_mb gogc scale scale_pct\n\n" +
|
||||
" config_get_bool enabled \"main\" \"enabled\" \"0\"\n" +
|
||||
" [ \"$enabled\" -eq \"1\" ] || return 0\n\n" +
|
||||
" config_get config_file \"main\" \"conffile\" \"/etc/sing-box/config.json\"\n" +
|
||||
@@ -394,10 +394,32 @@ function managed_service_text() {
|
||||
" procd_set_param limits core=\"unlimited\"\n" +
|
||||
" procd_set_param limits nofile=\"1000000 1000000\"\n" +
|
||||
" mem_total_kb=\"$(awk '/MemTotal/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)\"\n" +
|
||||
" if [ \"$mem_total_kb\" -gt 0 ] && [ \"$mem_total_kb\" -lt 262144 ]; then\n" +
|
||||
" mem_limit_mb=$(( mem_total_kb / 1024 * 35 / 100 ))\n" +
|
||||
" [ \"$mem_limit_mb\" -lt 24 ] && mem_limit_mb=24\n" +
|
||||
" procd_set_param env GOMEMLIMIT=\"${mem_limit_mb}MiB\"\n" +
|
||||
" if [ \"$mem_total_kb\" -gt 0 ]; then\n" +
|
||||
" if [ \"$mem_total_kb\" -lt 131072 ]; then\n" +
|
||||
" mem_limit_mb=$(( mem_total_kb / 1024 * 30 / 100 ))\n" +
|
||||
" [ \"$mem_limit_mb\" -lt 16 ] && mem_limit_mb=16\n" +
|
||||
" gogc=20\n" +
|
||||
" elif [ \"$mem_total_kb\" -lt 262144 ]; then\n" +
|
||||
" mem_limit_mb=$(( mem_total_kb / 1024 * 35 / 100 ))\n" +
|
||||
" [ \"$mem_limit_mb\" -lt 24 ] && mem_limit_mb=24\n" +
|
||||
" gogc=25\n" +
|
||||
" elif [ \"$mem_total_kb\" -lt 524288 ]; then\n" +
|
||||
" mem_limit_mb=$(( mem_total_kb / 1024 * 40 / 100 ))\n" +
|
||||
" gogc=30\n" +
|
||||
" else\n" +
|
||||
" mem_limit_mb=$(( mem_total_kb / 1024 * 30 / 100 ))\n" +
|
||||
" [ \"$mem_limit_mb\" -gt 256 ] && mem_limit_mb=256\n" +
|
||||
" gogc=40\n" +
|
||||
" fi\n" +
|
||||
" if [ -r \"/etc/tachyon/mem_scale\" ]; then\n" +
|
||||
" scale=\"$(cat /etc/tachyon/mem_scale 2>/dev/null)\"\n" +
|
||||
" scale_pct=\"$(awk -v s=\"$scale\" 'BEGIN { pct=int(s*100); if (pct < 20) pct=20; if (pct > 100) pct=100; print pct }')\"\n" +
|
||||
" if [ -n \"$scale_pct\" ] && [ \"$scale_pct\" -lt 100 ]; then\n" +
|
||||
" mem_limit_mb=$(( mem_limit_mb * scale_pct / 100 ))\n" +
|
||||
" [ \"$mem_limit_mb\" -lt 12 ] && mem_limit_mb=12\n" +
|
||||
" fi\n" +
|
||||
" fi\n" +
|
||||
" procd_set_param env GOMEMLIMIT=\"${mem_limit_mb}MiB\" GOGC=\"$gogc\"\n" +
|
||||
" fi\n" +
|
||||
" procd_set_param term_timeout 15\n" +
|
||||
" procd_set_param respawn\n" +
|
||||
@@ -450,8 +472,8 @@ function prepare_service_disabled() {
|
||||
function configure_service() {
|
||||
let settings = uci_settings();
|
||||
|
||||
if (sing_box_compressed_marker_set() && !install_managed_service_script()) {
|
||||
log_message("Failed to install managed sing-box service for compressed binary. Aborted.", "fatal");
|
||||
if (!managed_service_installed() && !install_managed_service_script()) {
|
||||
log_message("Failed to install managed sing-box service. Aborted.", "fatal");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user