--- SerialImp.c 2006-06-03 21:51:15.383224000 -0400 +++ ../../rxtx-2.1-7-144/src/SerialImp.c 2006-06-03 21:45:50.962728000 -0400 @@ -1212,6 +1212,10 @@ for(i=0;;i++) { report_verbose("drain_loop: looping\n"); + if( eis->eventloop_interrupted ) + { + goto end; + } #if defined(__sun__) /* FIXME: No time to test on all OS's for production */ if (usleep(5000)) { @@ -1256,7 +1260,7 @@ } else { - report("drain_loop: received EINTR\n"); + report("drain_loop: received EINTR in tcdrain\n"); } } end: @@ -4786,6 +4790,20 @@ #if !defined(TIOCSERGETLSR) && !defined(WIN32) /* make sure that the drainloop unblocks from tcdrain */ pthread_kill(index->drain_tid, SIGABRT); + /* TODO use wait/join/SIGCHLD/?? instead of sleep? */ + usleep(50 * 1000); + /* + Under normal conditions, SIGABRT will unblock tcdrain. However + a non-responding USB device combined with an unclean driver + may still block. This is very ugly because it may block the call + to close indefinetly. + */ + if (index->closing != 1) { + /* good bye tcdrain, and thanks for all the fish */ + report("interruptEventLoop: canceling blocked drain thread\n"); + pthread_cancel(index->drain_tid); + index->closing = 1; + } #endif report("interruptEventLoop: interrupted\n"); }