mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(serial): контракт SerValid — платформенный, ноль значит разное
Ноль на Unix и на Windows означает не одно и то же, и одной проверкой тут не обойтись. На Unix это законный дескриптор (при закрытом стандартном вводе fpOpen отдаёт именно его), а ядро Windows нулевой хендл не выдаёт никогда — там ноль это либо отказ RTL, либо неинициализированное поле. Внутренний путь был безопасен и раньше (SerOpen переводит ноль RTL в SER_INVALID_HANDLE, свои поля инициализируются им же), но публичный контракт для значения, пришедшего извне, оказывался неверным. Теперь проверка разведена по платформам. ★Стенд научился ПРОГОНЯТЬ windows-ветку, а не только компилировать её. Заглушка модуля Serial — чистый Паскаль, поэтому ветку можно собрать и запустить прямо на Linux: test/platform/win_probe проверяет перевод нулевого хендла в SER_INVALID_HANDLE, ответ SerValid и правило имени COM10+. До сих пор у windows-пути обёртки не было никакого поведенческого покрытия вовсе. Негативный контроль: если убрать windows-ветку из SerValid, прогон падает на «★нулевой хендл под Windows негоден». Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bkwwyj7xVRrqnSVEseTRfV
This commit is contained in:
+12
-6
@@ -424,14 +424,20 @@ begin
|
||||
end;
|
||||
|
||||
function SerValid(Handle: TSerialHandle): Boolean;
|
||||
// ★Ноль значит РАЗНОЕ на разных системах, и одной проверкой тут не обойтись.
|
||||
begin
|
||||
// ★Ноль — ЗАКОННЫЙ дескриптор на Unix: если стандартный ввод закрыт (демон,
|
||||
// запуск из службы), fpOpen отдаст именно 0, и объявлять такой порт ошибкой
|
||||
// нельзя — он не только не заработает, но и не закроется, потому что
|
||||
// SerClose тоже смотрит сюда. Признак неудачи ровно один и на всех
|
||||
// платформах: SER_INVALID_HANDLE. Ноль, который RTL под Windows отдаёт при
|
||||
// отказе, переводится в него внутри SerOpen.
|
||||
{$IFDEF WINDOWS}
|
||||
// Ядро Windows нулевой хендл не выдаёт никогда: ноль здесь — либо отказ RTL
|
||||
// (SerOpen переводит его в SER_INVALID_HANDLE), либо просто неинициализированное
|
||||
// поле. Отвергаем, чтобы контракт был верен и для значения, пришедшего извне.
|
||||
Result := (Handle <> SER_INVALID_HANDLE) and (Handle <> 0);
|
||||
{$ELSE}
|
||||
// А на Unix ноль ЗАКОНЕН: при закрытом стандартном вводе (демон, запуск из
|
||||
// службы) fpOpen отдаст именно его. Объявить такой порт ошибкой значит не
|
||||
// только потерять рабочий порт, но и не закрыть дескриптор — SerClose
|
||||
// смотрит сюда же. Признак неудачи один: SER_INVALID_HANDLE.
|
||||
Result := Handle <> SER_INVALID_HANDLE;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
function SerDefaultPortName(Index: Integer): string;
|
||||
|
||||
Reference in New Issue
Block a user