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