fix(errors): перестать глотать сбои записи состояния в пустых catch
Пустых catch в кодовой базе около полусотни, и они не одинаковые. Большинство выражает намерение: fs.unlink бросает на ENOENT, а вызывающий говорит «пусть этого файла не будет», и отсутствующий файл это условие уже выполняет; разбор json в цикле пропускает мусорную строку и берёт следующую. Такие места теперь несут пояснение, почему пустое тело здесь и есть правильный ответ. Семь мест к этому классу не относились: там сбой означал потерю состояния, а дальше код шёл так, будто всё получилось. Watchdog писал через пустой catch файл лока перезапуска прокси, шкалу GOMEMLIMIT после OOM, бэкап конфига и метку keepalive. Не лёгший лок означает, что следующий тик перезапустит прокси заново, а счётчик rate-limit об этом не узнает; не записанная метка keepalive заставляет init.d считать watchdog мёртвым и перезапускать его. Все четыре теперь идут через write_state_file, который логирует отказ. Метка пишется на каждом тике uloop, поэтому безусловная строка залила бы syslog именно при переполненной файловой системе — там, где лог нужнее всего; вместо этого каждый путь сообщает о первом отказе и молчит до следующего успеха, что заодно делает видимым восстановление. Контроллер разбирал /etc/sing-box/config.json ради портов http и tproxy и при неудаче молча брал 4534 и 4530. Watchdog после этого опрашивает не тот порт, вечно считает прокси нерабочим и лечит его по кругу — при том, что в логе нет ничего, что связало бы это с конфигом. Разбор вынесен в общую функцию, которая сообщает о непарсящемся конфиге один раз на процесс. Telegram молча терял карту callback-токенов: токен уже вшит в клавиатуру к моменту записи, поэтому провал отдаёт пользователю кнопку, которая на нажатие ответит «кнопка устарела». Обновление списков молча теряло маркер отложенного применения nft — списки обновлены на диске и до nftables не доехали никогда, а строкой выше в лог написано, что маркер сохраняется. urltest молча выкидывал битое регулярное выражение из конфига пользователя, отчего группа тихо подхватывала меньше outbound-ов, чем сказано в конфиге. tests/heal_escalation.sh проверял порядок строк по литералу fs.writefile для лока и обновлён под новый вызов.
This commit is contained in:
@@ -226,6 +226,9 @@ function write_state_file(path, value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The empty catch is the point: every caller means "make sure this path is
|
||||
// gone", and an absent file already satisfies that. fs.unlink throws on ENOENT,
|
||||
// so the alternative is a stat() race with no better outcome.
|
||||
function remove_file(path) {
|
||||
try {
|
||||
fs.unlink(as_string(path));
|
||||
@@ -1682,6 +1685,9 @@ function output_json_object(path) {
|
||||
return value;
|
||||
}
|
||||
catch (e) {
|
||||
// A job state file written by a worker that died mid-write is not JSON
|
||||
// as a whole. The line scan below recovers the last complete object in
|
||||
// it, which is the point of the fallback.
|
||||
}
|
||||
|
||||
let result = null;
|
||||
@@ -1696,6 +1702,8 @@ function output_json_object(path) {
|
||||
result = value;
|
||||
}
|
||||
catch (e) {
|
||||
// A partial line is expected here - that is what made the whole-file
|
||||
// parse above fail. Skip it and keep the last complete one.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2703,7 +2711,19 @@ function list_update() {
|
||||
log_message("Waiting for reload lock to apply nft rules", "debug");
|
||||
if (!acquire_runtime_lock(RELOAD_LOCK_DIR, true)) {
|
||||
log_message("Could not acquire reload lock for nft apply; saving pending marker for next attempt", "warn");
|
||||
try { fs.writefile("/tmp/tachyon_list_update_pending_nft", as_string(now_seconds())); } catch(e) {}
|
||||
// Without this marker the deferred apply is lost for good — nothing else
|
||||
// records that the nft phase still owes work. An empty catch here meant
|
||||
// the lists were updated on disk and never reached nftables, with the
|
||||
// "saving pending marker" line above as the only (untrue) evidence.
|
||||
let marker_written = false;
|
||||
try {
|
||||
marker_written = fs.writefile("/tmp/tachyon_list_update_pending_nft", as_string(now_seconds())) != null;
|
||||
}
|
||||
catch (e) {
|
||||
log_message("Failed to save pending nft marker, this list update will not be re-applied: " + as_string(e), "err");
|
||||
}
|
||||
if (!marker_written)
|
||||
log_message("Failed to save pending nft marker, this list update will not be re-applied", "err");
|
||||
list_update_pid_end();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user