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