Index: src/emx/include/emx/io.h
===================================================================
--- src/emx/include/emx/io.h	(revision 3742)
+++ src/emx/include/emx/io.h	(working copy)
@@ -302,6 +302,24 @@
 #define STREAM_LOCK_NOWAIT(f)   stream_trylock(f)
 #define STREAM_UNLOCKED(f)      ((f)->__uVersion == _FILE_STDIO_VERSION && _fmutex_available(&(f)->__u.__fsem))
 
+typedef struct __STREAM_XCPTREGREC
+{
+    void *apv[2]; // EXCEPTIONREGISTRATIONRECORD
+    struct __sFILE *file;
+    unsigned fs;
+} __STREAM_XCPTREGREC, *__STREAM_PXCPTREGREC;
+
+void __stream_xcpt_init(__STREAM_PXCPTREGREC pRegRec);
+void __stream_xcpt_done(__STREAM_PXCPTREGREC pRegRec);
+
+#define STREAM_XCPT_BEGIN       { __STREAM_XCPTREGREC __stream_xcptregec; __stream_xcpt_init(&__stream_xcptregec);
+#define STREAM_XCPT_END         __stream_xcpt_done(&__stream_xcptregec); }
+
+#define STREAM_XCPT_LOCK(f)         do { __stream_xcptregec.file = f; stream_lock(f); } while (0)
+#define STREAM_XCPT_UNLOCK(f)       do { stream_unlock(f); __stream_xcptregec.file = NULL; } while (0)
+#define STREAM_XCPT_LOCK_NOWAIT(f)  (stream_trylock(f) ? (__stream_xcptregec.file = f, 1) : 0)
+#define STREAM_XCPT_UNLOCK_END(f)   do { stream_unlock(f); __stream_xcptregec.file = NULL; __stream_xcpt_done(&__stream_xcptregec); } while (0)
+
 #endif /* __FILE_FSEM_DECLARED */
 
 struct __libc_FileHandle;
Index: src/emx/src/lib/app/stdio.c
===================================================================
--- src/emx/src/lib/app/stdio.c	(revision 3742)
+++ src/emx/src/lib/app/stdio.c	(working copy)
@@ -1,6 +1,9 @@
 /* stdio.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
                      -- Copyright (c) 2003-2004 by knut st. osmundsen */
 
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+
 #include "libc-alias.h"
 #include <sys/builtin.h>        /* For <sys/fmutex.h> */
 #include <sys/fmutex.h>
@@ -157,6 +160,7 @@
 _CRT_EXIT1(_exit_streams)
 
 
+#if defined (__FILE_FSEM_DECLARED)
 
 /**
  * Fatal stream error.
@@ -180,3 +184,52 @@
     return 0;
 }
 
+/**
+ * Exception handler for STREAM_XCPT_LOCK()/STREAM_XCPT_UNLOCK().
+ *
+ * Releases the stream lock on thread termination.
+ */
+ULONG __stream_exception(EXCEPTIONREPORTRECORD *report,
+                         EXCEPTIONREGISTRATIONRECORD *registration,
+                         CONTEXTRECORD *context,
+                         void *dummy);
+ULONG __stream_exception(EXCEPTIONREPORTRECORD *report,
+                         EXCEPTIONREGISTRATIONRECORD *registration,
+                         CONTEXTRECORD *context,
+                         void *dummy)
+{
+    __STREAM_PXCPTREGREC pRegRec = (__STREAM_PXCPTREGREC)registration;
+
+    if (report->fHandlerFlags & EH_UNWINDING ||
+        report->ExceptionNum == XCPT_ASYNC_PROCESS_TERMINATE ||
+        report->ExceptionNum == XCPT_PROCESS_TERMINATE)
+    {
+        if (pRegRec->file)
+        {
+            // make sure we won't be called again
+            DosUnsetExceptionHandler(registration);
+            // unlock the stream mutex
+            STREAM_UNLOCK(pRegRec->file);
+        }
+    }
+    return XCPT_CONTINUE_SEARCH;
+}
+
+void __stream_xcpt_init(__STREAM_PXCPTREGREC pRegRec)
+{
+    __asm__ __volatile__ ("movl %%fs, %%eax; movl %%eax,%0; movl $DosTIB, %%eax; movl %%eax, %%fs" : : "m" (pRegRec->fs) : "%eax" );
+
+    ((PEXCEPTIONREGISTRATIONRECORD)pRegRec)->prev_structure = 0;
+    ((PEXCEPTIONREGISTRATIONRECORD)pRegRec)->ExceptionHandler = __stream_exception;
+    pRegRec->file = 0;
+    DosSetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)pRegRec);
+}
+
+void __stream_xcpt_done(__STREAM_PXCPTREGREC pRegRec)
+{
+    DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)pRegRec);
+
+    __asm__ __volatile__ ("movl %0, %%eax; movl %%eax,%%fs;" : : "m" (pRegRec->fs) : "%eax" );
+}
+
+#endif /* __FILE_FSEM_DECLARED */
Index: src/emx/src/lib/io/fflush.c
===================================================================
--- src/emx/src/lib/io/fflush.c	(revision 3742)
+++ src/emx/src/lib/io/fflush.c	(working copy)
@@ -68,6 +68,8 @@
   int result, n;
   struct streamvec *sv;
 
+  STREAM_XCPT_BEGIN
+
   result = 0;
   if (stream == NULL)
     {
@@ -79,8 +81,11 @@
       return result;
     }
 
-  STREAM_LOCK (stream);
+  STREAM_XCPT_LOCK (stream);
   result = fflush_unlocked (stream);
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/fgetc.c
===================================================================
--- src/emx/src/lib/io/fgetc.c	(revision 3742)
+++ src/emx/src/lib/io/fgetc.c	(working copy)
@@ -15,9 +15,16 @@
 
 int _STD(fgetc)(FILE *stream)
 {
-    STREAM_LOCK(stream);
-    int rc = _getc_inline(stream);
-    STREAM_UNLOCK(stream);
+    int rc;
+
+    STREAM_XCPT_BEGIN
+
+    STREAM_XCPT_LOCK(stream);
+    rc = _getc_inline(stream);
+    STREAM_XCPT_UNLOCK(stream);
+
+    STREAM_XCPT_END
+
     return rc;
 }
 
Index: src/emx/src/lib/io/fgets.c
===================================================================
--- src/emx/src/lib/io/fgets.c	(revision 3742)
+++ src/emx/src/lib/io/fgets.c	(working copy)
@@ -10,9 +10,16 @@
 
 char *_STD(fgets)(char *buffer, int n, FILE *stream)
 {
-    STREAM_LOCK(stream);
-    char *psz = fgets_unlocked(buffer, n, stream);
-    STREAM_UNLOCK(stream);
+    char *psz;
+
+    STREAM_XCPT_BEGIN
+
+    STREAM_XCPT_LOCK(stream);
+    psz = fgets_unlocked(buffer, n, stream);
+    STREAM_XCPT_UNLOCK(stream);
+
+    STREAM_XCPT_END
+
     return psz;
 }
 
Index: src/emx/src/lib/io/flushall.c
===================================================================
--- src/emx/src/lib/io/flushall.c	(revision 3742)
+++ src/emx/src/lib/io/flushall.c	(working copy)
@@ -12,17 +12,22 @@
   int i, n;
   struct streamvec *sv;
 
+  STREAM_XCPT_BEGIN
+
   /* Ignore locked streams to avoid deadlock on process
      termination. */
 
   n = 0;
   for (sv = _streamvec_head; sv != NULL; sv = sv->pNext)
     for (i = 0; i < sv->cFiles; ++i)
-      if ((sv->aFiles[i]._flags & _IOOPEN) && STREAM_LOCK_NOWAIT (&sv->aFiles[i]))
+      if ((sv->aFiles[i]._flags & _IOOPEN) && STREAM_XCPT_LOCK_NOWAIT (&sv->aFiles[i]))
         {
           ++n;
           fflush_unlocked (&sv->aFiles[i]);
-          STREAM_UNLOCK (&sv->aFiles[i]);
+          STREAM_XCPT_UNLOCK (&sv->aFiles[i]);
         }
+
+  STREAM_XCPT_END
+
   return n;
 }
Index: src/emx/src/lib/io/fprintf.c
===================================================================
--- src/emx/src/lib/io/fprintf.c	(revision 3742)
+++ src/emx/src/lib/io/fprintf.c	(working copy)
@@ -14,15 +14,20 @@
   int result;
   void *tb;
 
+  STREAM_XCPT_BEGIN
+
   va_start (arg_ptr, format);
-  STREAM_LOCK (stream);
+  STREAM_XCPT_LOCK (stream);
   if (nbuf (stream))
     _fbuf (stream);
   _tmpbuf (stream, tb);
   result = _output (stream, format, arg_ptr);
   if (_endbuf (stream) != 0)
     result = -1;
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
   va_end (arg_ptr);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/fputc.c
===================================================================
--- src/emx/src/lib/io/fputc.c	(revision 3742)
+++ src/emx/src/lib/io/fputc.c	(working copy)
@@ -16,9 +16,14 @@
 {
     int r;
 
-    STREAM_LOCK(stream);
+    STREAM_XCPT_BEGIN
+
+    STREAM_XCPT_LOCK(stream);
     r = _putc_inline(c, stream);
-    STREAM_UNLOCK(stream);
+    STREAM_XCPT_UNLOCK(stream);
+
+    STREAM_XCPT_END
+
     return r;
 }
 
@@ -31,8 +36,13 @@
 {
     int r;
 
-    STREAM_LOCK(stream);
+    STREAM_XCPT_BEGIN
+
+    STREAM_XCPT_LOCK(stream);
     r = _putc_inline(c, stream);
-    STREAM_UNLOCK(stream);
+    STREAM_XCPT_UNLOCK(stream);
+
+    STREAM_XCPT_END
+
     return r;
 }
Index: src/emx/src/lib/io/fread.c
===================================================================
--- src/emx/src/lib/io/fread.c	(revision 3742)
+++ src/emx/src/lib/io/fread.c	(working copy)
@@ -13,9 +13,16 @@
 
 size_t _STD(fread)(void *buffer, size_t size, size_t count, FILE *stream)
 {
-    STREAM_LOCK(stream);
-    size_t cb = fread_unlocked(buffer, size, count, stream);
-    STREAM_UNLOCK(stream);
+    size_t cb;
+
+    STREAM_XCPT_BEGIN
+
+    STREAM_XCPT_LOCK(stream);
+    cb = fread_unlocked(buffer, size, count, stream);
+    STREAM_XCPT_UNLOCK(stream);
+
+    STREAM_XCPT_END
+
     return cb;
 }
 
Index: src/emx/src/lib/io/fscanf.c
===================================================================
--- src/emx/src/lib/io/fscanf.c	(revision 3742)
+++ src/emx/src/lib/io/fscanf.c	(working copy)
@@ -13,10 +13,15 @@
   va_list arg_ptr;
   int result;
 
+  STREAM_XCPT_BEGIN
+
   va_start (arg_ptr, format);
-  STREAM_LOCK (stream);
+  STREAM_XCPT_LOCK (stream);
   result = _input (stream, format, arg_ptr);
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
   va_end (arg_ptr);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/fseek.c
===================================================================
--- src/emx/src/lib/io/fseek.c	(revision 3742)
+++ src/emx/src/lib/io/fseek.c	(working copy)
@@ -182,9 +182,14 @@
 {
     int result;
 
-    STREAM_LOCK (stream);
+    STREAM_XCPT_BEGIN
+
+    STREAM_XCPT_LOCK (stream);
     result = _fseek_unlocked (stream, offset, origin);
-    STREAM_UNLOCK (stream);
+    STREAM_XCPT_UNLOCK (stream);
+
+    STREAM_XCPT_END
+
     return result;
 }
 
Index: src/emx/src/lib/io/ftell.c
===================================================================
--- src/emx/src/lib/io/ftell.c	(revision 3742)
+++ src/emx/src/lib/io/ftell.c	(working copy)
@@ -102,9 +102,14 @@
 {
   off_t off;
 
-  STREAM_LOCK (stream);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stream);
   off = _ftello_unlocked (stream);
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+
+  STREAM_XCPT_END
+
   return off;
 }
 
Index: src/emx/src/lib/io/fwide.c
===================================================================
--- src/emx/src/lib/io/fwide.c	(revision 3742)
+++ src/emx/src/lib/io/fwide.c	(working copy)
@@ -48,11 +48,13 @@
     LIBCLOG_ENTER("pStream=%p iOrientation=%d\n", (void *)pStream, iOrientation);
     int iRet = -1;
 #if 0 /** @todo LIBC07 */
-    STREAM_LOCK(pStream);
+    STREAM_XCPT_BEGIN
+    STREAM_XCPT_LOCK(pStream);
     if (iOrientation != 0 && pStream->__iOrientation == 0)
         pStream->__iOrientation = iOrientation > 0 ? 1 : -1;
     iRet =  pStream->__iOrientation;
-    STREAM_UNLOCK(pStream);
+    STREAM_XCPT_UNLOCK(pStream);
+    STREAM_XCPT_END
 #endif
     LIBCLOG_RETURN_INT(iRet);
 }
Index: src/emx/src/lib/io/fwrite.c
===================================================================
--- src/emx/src/lib/io/fwrite.c	(revision 3742)
+++ src/emx/src/lib/io/fwrite.c	(working copy)
@@ -168,8 +168,13 @@
 {
   size_t r;
 
-  STREAM_LOCK (stream);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stream);
   r = fwrite_unlocked (buffer, size, count, stream);
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+
+  STREAM_XCPT_END
+
   return r;
 }
Index: src/emx/src/lib/io/getdelim.c
===================================================================
--- src/emx/src/lib/io/getdelim.c	(revision 3742)
+++ src/emx/src/lib/io/getdelim.c	(working copy)
@@ -76,13 +76,16 @@
         *pcchString = 128;
     }
 
-    /*
-     * Lock the stream and start reading.
-     */
-    STREAM_LOCK(pStream);
     ssize_t rc = 0;
     char *psz = *ppszString;
     char *pszEnd = psz + *pcchString - 1;
+
+    STREAM_XCPT_BEGIN
+
+    /*
+     * Lock the stream and start reading.
+     */
+    STREAM_XCPT_LOCK(pStream);
     for (;;)
     {
         /** @todo this can be done faster by accessing what's in the buffer directly.
@@ -117,7 +120,9 @@
         if (ch == chDelim)
             break;
     }
-    STREAM_UNLOCK(pStream);
+    STREAM_XCPT_UNLOCK(pStream);
+
+    STREAM_XCPT_END
 
     if (!rc)
         rc = psz - *ppszString;
Index: src/emx/src/lib/io/gets.c
===================================================================
--- src/emx/src/lib/io/gets.c	(revision 3742)
+++ src/emx/src/lib/io/gets.c	(working copy)
@@ -36,9 +36,16 @@
 
 char *_STD(gets)(char *buffer)
 {
-    STREAM_LOCK(stdin);
-    char *psz = gets_unlocked(buffer);
-    STREAM_UNLOCK(stdin);
+    char *psz;
+
+    STREAM_XCPT_BEGIN
+
+    STREAM_XCPT_LOCK(stdin);
+    psz = gets_unlocked(buffer);
+    STREAM_XCPT_UNLOCK(stdin);
+
+    STREAM_XCPT_END
+
     return psz;
 }
 
Index: src/emx/src/lib/io/printf.c
===================================================================
--- src/emx/src/lib/io/printf.c	(revision 3742)
+++ src/emx/src/lib/io/printf.c	(working copy)
@@ -14,15 +14,20 @@
   int result;
   void *tb;
 
+  STREAM_XCPT_BEGIN
+
   va_start (arg_ptr, format);
-  STREAM_LOCK (stdout);
+  STREAM_XCPT_LOCK (stdout);
   if (nbuf (stdout))
     _fbuf (stdout);
   _tmpbuf (stdout, tb);
   result = _output (stdout, format, arg_ptr);
   if (_endbuf (stdout) != 0)
     result = -1;
-  STREAM_UNLOCK (stdout);
+  STREAM_XCPT_UNLOCK (stdout);
   va_end (arg_ptr);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/puts.c
===================================================================
--- src/emx/src/lib/io/puts.c	(revision 3742)
+++ src/emx/src/lib/io/puts.c	(working copy)
@@ -11,9 +11,16 @@
 
 int _STD(puts) (const char *string)
 {
-    STREAM_LOCK(stdout);
-    int rc = puts_unlocked(string);
-    STREAM_UNLOCK(stdout);
+    int rc;
+
+    STREAM_XCPT_BEGIN
+    
+    STREAM_XCPT_LOCK(stdout);
+    rc = puts_unlocked(string);
+    STREAM_XCPT_UNLOCK(stdout);
+    
+    STREAM_XCPT_END
+    
     return rc;
 }
 
Index: src/emx/src/lib/io/rewind.c
===================================================================
--- src/emx/src/lib/io/rewind.c	(revision 3742)
+++ src/emx/src/lib/io/rewind.c	(working copy)
@@ -9,9 +9,11 @@
 
 void _STD(rewind) (FILE *stream)
 {
-  STREAM_LOCK (stream);
+  STREAM_XCPT_BEGIN
+  STREAM_XCPT_LOCK (stream);
   fflush_unlocked (stream);
   _fseek_unlocked (stream, 0, SEEK_SET);
   stream->_flags &= ~_IOERR;
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+  STREAM_XCPT_END
 }
Index: src/emx/src/lib/io/scanf.c
===================================================================
--- src/emx/src/lib/io/scanf.c	(revision 3742)
+++ src/emx/src/lib/io/scanf.c	(working copy)
@@ -13,10 +13,15 @@
   va_list arg_ptr;
   int result;
 
+  STREAM_XCPT_BEGIN
+
   va_start (arg_ptr, format);
-  STREAM_LOCK (stdin);
+  STREAM_XCPT_LOCK (stdin);
   result = _input (stdin, format, arg_ptr);
-  STREAM_UNLOCK (stdin);
+  STREAM_XCPT_UNLOCK (stdin);
   va_end (arg_ptr);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/setvbuf.c
===================================================================
--- src/emx/src/lib/io/setvbuf.c	(revision 3742)
+++ src/emx/src/lib/io/setvbuf.c	(working copy)
@@ -13,7 +13,9 @@
       || (mode != _IONBF && mode != _IOFBF && mode != _IOLBF))
     return EOF;
 
-  STREAM_LOCK (stream);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stream);
   fflush_unlocked (stream);
   if ((stream->_flags & _IOBUFMASK) == _IOBUFLIB)
     free (stream->_buffer);
@@ -48,7 +50,7 @@
       buffer = malloc (size);
       if (buffer == NULL)
         {
-          STREAM_UNLOCK (stream);
+          STREAM_XCPT_UNLOCK_END (stream);
           return EOF;
         }
       stream->_buf_size = size;
@@ -58,6 +60,9 @@
   stream->_ptr = stream->_buffer;
   stream->_rcount = 0;
   stream->_wcount = 0;
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+
+  STREAM_XCPT_END
+
   return 0;
 }
Index: src/emx/src/lib/io/ungetc.c
===================================================================
--- src/emx/src/lib/io/ungetc.c	(revision 3742)
+++ src/emx/src/lib/io/ungetc.c	(working copy)
@@ -153,8 +153,13 @@
 {
   int result;
 
-  STREAM_LOCK (stream);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stream);
   result = _ungetc_nolock (c, stream);
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/vfprintf.c
===================================================================
--- src/emx/src/lib/io/vfprintf.c	(revision 3742)
+++ src/emx/src/lib/io/vfprintf.c	(working copy)
@@ -12,13 +12,18 @@
   int result;
   void *tb;
 
-  STREAM_LOCK (stream);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stream);
   if (nbuf (stream))
     _fbuf (stream);
   _tmpbuf (stream, tb);
   result = _output (stream, format, arg_ptr);
   if (_endbuf (stream) != 0)
     result = -1;
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/vfscanf.c
===================================================================
--- src/emx/src/lib/io/vfscanf.c	(revision 3742)
+++ src/emx/src/lib/io/vfscanf.c	(working copy)
@@ -12,8 +12,13 @@
 {
   int r;
 
-  STREAM_LOCK (stream);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stream);
   r = _input (stream, format, arg_ptr);
-  STREAM_UNLOCK (stream);
+  STREAM_XCPT_UNLOCK (stream);
+
+  STREAM_XCPT_END
+
   return r;
 }
Index: src/emx/src/lib/io/vprintf.c
===================================================================
--- src/emx/src/lib/io/vprintf.c	(revision 3742)
+++ src/emx/src/lib/io/vprintf.c	(working copy)
@@ -12,13 +12,18 @@
   int result;
   void *tb;
 
-  STREAM_LOCK (stdout);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stdout);
   if (nbuf (stdout))
     _fbuf (stdout);
   _tmpbuf (stdout, tb);
   result = _output (stdout, format, arg_ptr);
   if (_endbuf (stdout) != 0)
     result = -1;
-  STREAM_UNLOCK (stdout);
+  STREAM_XCPT_UNLOCK (stdout);
+
+  STREAM_XCPT_END
+
   return result;
 }
Index: src/emx/src/lib/io/vscanf.c
===================================================================
--- src/emx/src/lib/io/vscanf.c	(revision 3742)
+++ src/emx/src/lib/io/vscanf.c	(working copy)
@@ -12,8 +12,13 @@
 {
   int r;
 
-  STREAM_LOCK (stdin);
+  STREAM_XCPT_BEGIN
+
+  STREAM_XCPT_LOCK (stdin);
   r = _input (stdin, format, arg_ptr);
-  STREAM_UNLOCK (stdin);
+  STREAM_XCPT_UNLOCK (stdin);
+
+  STREAM_XCPT_END
+
   return r;
 }
