Back
...

========
Subject: Глюки в AcyncPro 2.02 и как с ними боpоться...
From: Boris Loboda <Boris.Loboda@f256.n461.z2.fidonet.org>


Пpuвeт, All!

В общем, как я уже обещал...
=== Cut ===

Глюки в Async Pro 2.02 и как от них избавиться.

1.)
Глюк......: Довольно часто наблюдаются зависания на процедуре
ApdComPort.FlushOutBuffer.
Причина...: е совсем понятна, но связана с функцией Win32FlushComm
в модуле AWWIN32.PAS, виснет на операторе:
WaitForSingleObject(GeneralEvent, INFINITE); {!!.02}
При INFINITE тайм-ауте не приходит GeneralEvent.
Устранение: Задать какое-либо разумное время ожидания, типа 500.1000.
Либо вообще убрать оператор вместе с предшествующим ему
SetEvent(OutFlushEvent), у меня именно так и сделано,
никаких траблов не наблюдается. у а по большому счету нужно
все-таки разобраться, почему не приходит GeneralEvent, кто
его не устанавливает, или кто его сбрасывает до того, как
он отработает в функции Win32FlushComm. Если кто-нибудь
разберется с этим, обязательно сообщите мне.

2.)
Глюк......: ApdComPort.CharReady при полностью заполненном входном
буфере возвращает FALSE.
Причина...: Кроется в функции pCharReady в модуле AWUSER.PAS.
Результат функции возвращается так:
pCharReady := DBufHead <> DBufTail;
DBufHead и DBufTail - это указатели на начало и конец
входного кругового буфера. Они равны между собой не только
при пустом буфере (что вполне естественно), но и при полностью
забитом (что противоестественно).
Устранение: Заменить вышеприведенную строку на такую:
pCharReady := (DBufHead <> DBufTail) or DispatchFull;

3.)
Глюк......: При записи данных в порт не проверяется количество фактически
записанных байт. Указатели в выходном буфере после записи
корректируются на количество байт, которые пытались писать,
хотя функция WriteFile(...) возвращает фактическое количество
байт которые ушли в порт. Глюк не смертельный, порт не завесит,
но может приводить к потере данных и будет заставлять протокол
перепосылать блоки.
Это модуль AWUSER.PAS (строка ~5100),
procedure ProcessOutputEvent(H : TComHandle);
...
Сначала считается смещение для указателей выходного буфера:
if OBufTail < OBufHead then begin
{not wrapped, so write it all}
NewTail := OBufHead;
WrapToStart := False;
end else begin
{wrapped, so just write up to the end}
NewTail := OutQue;
WrapToStart := True;
end;
NumToWrite := NewTail - OBufTail;
Делается запись в порт:
Ok := WriteFile(Cid,
OBuffer^[OBufTail],
NumToWrite,
NumWritten,
@OutOL);
NumWritten - сколько байт записалось.
иже, после завершения операции записи корректируются
указатели в выходном круговом буфере (в двух местах!) -
после того, как OK := WriteFile(...) = True и после
GetOverlappedResult(...):
if not WrapToStart then
OBufTail := NewTail
else
OBufTail := 0;
OBufFull := False;
После записи NumWritten уже никого не волнует, указатель
меняется на первоначально рассчитанное значение, исходя из
того, что все байтики которые мы писали, уехали в порт,
но в жизни так бывает не всегда...
Устранение: Я вставил такую процедуру на корректировку указателей:
procedure ChangeBufPointers;
begin
with ComPorts[H]^ do begin
OBufFull := OBufFull and (NumWritten = 0);
if not WrapToStart then begin
if NumToWrite = NumWritten then
OBufTail := NewTail
else Inc(OBufTail, NumWritten);
end
else begin
if NumToWrite = NumWritten then
OBufTail := 0
else Inc(OBufTail, NumWritten);
end;
end;
end;
... и вызываю ее вместо вышеприведенного участка кода.
Вы конечно скажете, что это длинно и несколько сумбурно,
но тем не менее, это лучше того, что было. Если у кого
будет время и энергия оптимизировать это - пожалуйста... :-)

P.S. Если кто заметил еще какие-нибудь глюки в APD 2.02 - пишите.
у и не мешало бы до конца разобраться с Win32FlushComm.
=== Cut ===

С наилучшими пожеланиями - Boris.
barry@audit.kharkov.com

23.01.99 20:00:15