Fix write deadlock with streaming serial devices
Brian Ford
ford@vss.fsi.com
Thu Jan 22 23:07:00 GMT 2004
This trivial patch fixes the problem reported here:
http://www.cygwin.com/ml/cygwin/2004-01/msg00664.html
Tested and confirmed by the reporter here:
http://www.cygwin.com/ml/cygwin/2004-01/msg00716.html
and by Martin Farnik in a previous private email discussion.
If the input buffer overflows because a device is streaming faster than
the application is reading, all serial communications cease and calls
return ERROR_OPERATION_ABORTED. In order to restart communication,
ClearCommError must be called. Without this patch, a deadlock inside
fhandler_serial::raw_write could occur.
Martin has supplied me with an strace log of another hang, but I have yet
to fully understand it. A patch for it is hopefully forth comming.
The fhandler_serial::raw_read patch is merely a suggestion to correct a
possible thinko. Feel free to ignore it, or correct my limited analysis.
Thanks.
2004-01-22 Brian Ford <ford@vss.fsi.com>
* fhandler_serial.cc (fhandler_serial::raw_write): Prevent a
deadlock when the input buffer overflows.
(fhandler_serial::raw_read): Correct to print the actual error
and only call PurgeComm when necessary.
--
Brian Ford
Senior Realtime Software Engineer
VITAL - Visual Simulation Systems
FlightSafety International
Phone: 314-551-8460
Fax: 314-551-8444
-------------- next part --------------
Index: fhandler_serial.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_serial.cc,v
retrieving revision 1.47
diff -u -p -r1.47 fhandler_serial.cc
--- fhandler_serial.cc 11 Dec 2003 18:07:42 -0000 1.47
+++ fhandler_serial.cc 22 Jan 2004 22:38:04 -0000
@@ -133,16 +133,16 @@ fhandler_serial::raw_read (void *ptr, si
continue;
err:
- PurgeComm (get_handle (), PURGE_RXABORT);
debug_printf ("err %E");
- if (GetLastError () == ERROR_OPERATION_ABORTED)
- n = 0;
- else
+ if (GetLastError () != ERROR_OPERATION_ABORTED)
{
+ PurgeComm (get_handle (), PURGE_RXABORT);
tot = -1;
__seterrno ();
break;
}
+
+ n = 0;
}
out:
@@ -169,6 +169,9 @@ fhandler_serial::raw_write (const void *
switch (GetLastError ())
{
case ERROR_OPERATION_ABORTED:
+ DWORD ev;
+ if (!ClearCommError (get_handle (), &ev, NULL)) goto err;
+ if (ev) termios_printf ("error detected %x", ev);
continue;
case ERROR_IO_PENDING:
break;
More information about the Cygwin-patches
mailing list