mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(tci): счётчик клиентских потоков переживал неудачный старт — Stop висел вечно
AcceptLoop делал InterLockedIncrement(FThreadCount) и следом создавал поток безо всякой защиты. Не родился поток (память, лимит потоков в системе) — исключение уходило из AcceptLoop и TTCIAcceptThread.Execute, accept-поток умирал при FRunning = True, а счётчик оставался ≥ 1 навсегда. Ждут его на шаге 4 TTCIServer.Stop БЕЗ таймаута (и намеренно: следом освобождаются и клиенты, и сам сервер), так что программа зависала и на выходе, и на любой смене настроек TCI. Инкремент остался до старта — переносить его после Start нельзя, там гонка с ThreadDone уходящего потока. Спавн обёрнут в try/except: счётчик возвращается назад, сокет гасится Kill, клиент метится FClosed и достаётся тик-потоку (ReapClients), как при обычном отключении. Объект потока уносит себя сам — упавший конструктор сразу, поднявшийся по FreeOnTerminate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1009,9 +1009,23 @@ begin
|
|||||||
Continue;
|
Continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Счётчик — ДО старта: иначе Stop успел бы проскочить шаг 4 между Start и
|
||||||
|
// первой строкой потока. ★А не родился поток (память, лимит потоков) —
|
||||||
|
// сразу возвращаем счётчик назад: ждут его на шаге 4 без таймаута, и
|
||||||
|
// лишняя единица подвешивала бы и выход из программы, и любую смену
|
||||||
|
// настроек TCI. Объект потока уносит себя сам: упавший конструктор — сразу,
|
||||||
|
// а поднявшийся — по FreeOnTerminate.
|
||||||
InterLockedIncrement(FThreadCount);
|
InterLockedIncrement(FThreadCount);
|
||||||
|
try
|
||||||
T := TTCIClientThread.Create(Self, Client);
|
T := TTCIClientThread.Create(Self, Client);
|
||||||
T.Start;
|
T.Start;
|
||||||
|
except
|
||||||
|
InterLockedDecrement(FThreadCount);
|
||||||
|
// Обслуживать клиента больше некому: гасим сокет и метим на освобождение
|
||||||
|
// — заберёт тик-поток (ReapClients), как и обычное отключение.
|
||||||
|
Client.Kill;
|
||||||
|
Client.FClosed := True;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user