Ticket #256: stream_panic.2.diff

File stream_panic.2.diff, 18.1 KB (added by dmik, 12 years ago)

Updated version, see comments

  • src/emx/include/emx/io.h

     
    302302#define STREAM_LOCK_NOWAIT(f)   stream_trylock(f)
    303303#define STREAM_UNLOCKED(f)      ((f)->__uVersion == _FILE_STDIO_VERSION && _fmutex_available(&(f)->__u.__fsem))
    304304
     305typedef struct __STREAM_XCPTREGREC
     306{
     307    void *apv[2]; // EXCEPTIONREGISTRATIONRECORD
     308    struct __sFILE *file;
     309    unsigned fs;
     310} __STREAM_XCPTREGREC, *__STREAM_PXCPTREGREC;
     311
     312void __stream_xcpt_init(__STREAM_PXCPTREGREC pRegRec);
     313void __stream_xcpt_done(__STREAM_PXCPTREGREC pRegRec);
     314
     315#define STREAM_XCPT_BEGIN       { __STREAM_XCPTREGREC __stream_xcptregec; __stream_xcpt_init(&__stream_xcptregec);
     316#define STREAM_XCPT_END         __stream_xcpt_done(&__stream_xcptregec); }
     317
     318#define STREAM_XCPT_LOCK(f)         do { __stream_xcptregec.file = f; stream_lock(f); } while (0)
     319#define STREAM_XCPT_UNLOCK(f)       do { stream_unlock(f); __stream_xcptregec.file = NULL; } while (0)
     320#define STREAM_XCPT_LOCK_NOWAIT(f)  (stream_trylock(f) ? (__stream_xcptregec.file = f, 1) : 0)
     321#define STREAM_XCPT_UNLOCK_END(f)   do { stream_unlock(f); __stream_xcptregec.file = NULL; __stream_xcpt_done(&__stream_xcptregec); } while (0)
     322
    305323#endif /* __FILE_FSEM_DECLARED */
    306324
    307325struct __libc_FileHandle;
  • src/emx/src/lib/app/stdio.c

     
    11/* stdio.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
    22                     -- Copyright (c) 2003-2004 by knut st. osmundsen */
    33
     4#define INCL_DOSEXCEPTIONS
     5#include <os2emx.h>
     6
    47#include "libc-alias.h"
    58#include <sys/builtin.h>        /* For <sys/fmutex.h> */
    69#include <sys/fmutex.h>
     
    157160_CRT_EXIT1(_exit_streams)
    158161
    159162
     163#if defined (__FILE_FSEM_DECLARED)
    160164
    161165/**
    162166 * Fatal stream error.
     
    180184    return 0;
    181185}
    182186
     187/**
     188 * Exception handler for STREAM_XCPT_LOCK()/STREAM_XCPT_UNLOCK().
     189 *
     190 * Releases the stream lock on thread termination.
     191 */
     192ULONG __stream_exception(EXCEPTIONREPORTRECORD *report,
     193                         EXCEPTIONREGISTRATIONRECORD *registration,
     194                         CONTEXTRECORD *context,
     195                         void *dummy);
     196ULONG __stream_exception(EXCEPTIONREPORTRECORD *report,
     197                         EXCEPTIONREGISTRATIONRECORD *registration,
     198                         CONTEXTRECORD *context,
     199                         void *dummy)
     200{
     201    __STREAM_PXCPTREGREC pRegRec = (__STREAM_PXCPTREGREC)registration;
     202
     203    if (report->fHandlerFlags & EH_UNWINDING ||
     204        report->ExceptionNum == XCPT_ASYNC_PROCESS_TERMINATE ||
     205        report->ExceptionNum == XCPT_PROCESS_TERMINATE)
     206    {
     207        if (pRegRec->file)
     208        {
     209            // make sure we won't be called again
     210            DosUnsetExceptionHandler(registration);
     211            // unlock the stream mutex
     212            STREAM_UNLOCK(pRegRec->file);
     213        }
     214    }
     215    return XCPT_CONTINUE_SEARCH;
     216}
     217
     218void __stream_xcpt_init(__STREAM_PXCPTREGREC pRegRec)
     219{
     220    __asm__ __volatile__ ("movl %%fs, %%eax; movl %%eax,%0; movl $DosTIB, %%eax; movl %%eax, %%fs" : : "m" (pRegRec->fs) : "%eax" );
     221
     222    ((PEXCEPTIONREGISTRATIONRECORD)pRegRec)->prev_structure = 0;
     223    ((PEXCEPTIONREGISTRATIONRECORD)pRegRec)->ExceptionHandler = __stream_exception;
     224    pRegRec->file = 0;
     225    DosSetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)pRegRec);
     226}
     227
     228void __stream_xcpt_done(__STREAM_PXCPTREGREC pRegRec)
     229{
     230    DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)pRegRec);
     231
     232    __asm__ __volatile__ ("movl %0, %%eax; movl %%eax,%%fs;" : : "m" (pRegRec->fs) : "%eax" );
     233}
     234
     235#endif /* __FILE_FSEM_DECLARED */
  • src/emx/src/lib/io/fflush.c

     
    6868  int result, n;
    6969  struct streamvec *sv;
    7070
     71  STREAM_XCPT_BEGIN
     72
    7173  result = 0;
    7274  if (stream == NULL)
    7375    {
     
    7981      return result;
    8082    }
    8183
    82   STREAM_LOCK (stream);
     84  STREAM_XCPT_LOCK (stream);
    8385  result = fflush_unlocked (stream);
    84   STREAM_UNLOCK (stream);
     86  STREAM_XCPT_UNLOCK (stream);
     87
     88  STREAM_XCPT_END
     89
    8590  return result;
    8691}
  • src/emx/src/lib/io/fgetc.c

     
    1515
    1616int _STD(fgetc)(FILE *stream)
    1717{
    18     STREAM_LOCK(stream);
    19     int rc = _getc_inline(stream);
    20     STREAM_UNLOCK(stream);
     18    int rc;
     19
     20    STREAM_XCPT_BEGIN
     21
     22    STREAM_XCPT_LOCK(stream);
     23    rc = _getc_inline(stream);
     24    STREAM_XCPT_UNLOCK(stream);
     25
     26    STREAM_XCPT_END
     27
    2128    return rc;
    2229}
    2330
  • src/emx/src/lib/io/fgets.c

     
    1010
    1111char *_STD(fgets)(char *buffer, int n, FILE *stream)
    1212{
    13     STREAM_LOCK(stream);
    14     char *psz = fgets_unlocked(buffer, n, stream);
    15     STREAM_UNLOCK(stream);
     13    char *psz;
     14
     15    STREAM_XCPT_BEGIN
     16
     17    STREAM_XCPT_LOCK(stream);
     18    psz = fgets_unlocked(buffer, n, stream);
     19    STREAM_XCPT_UNLOCK(stream);
     20
     21    STREAM_XCPT_END
     22
    1623    return psz;
    1724}
    1825
  • src/emx/src/lib/io/flushall.c

     
    1212  int i, n;
    1313  struct streamvec *sv;
    1414
     15  STREAM_XCPT_BEGIN
     16
    1517  /* Ignore locked streams to avoid deadlock on process
    1618     termination. */
    1719
    1820  n = 0;
    1921  for (sv = _streamvec_head; sv != NULL; sv = sv->pNext)
    2022    for (i = 0; i < sv->cFiles; ++i)
    21       if ((sv->aFiles[i]._flags & _IOOPEN) && STREAM_LOCK_NOWAIT (&sv->aFiles[i]))
     23      if ((sv->aFiles[i]._flags & _IOOPEN) && STREAM_XCPT_LOCK_NOWAIT (&sv->aFiles[i]))
    2224        {
    2325          ++n;
    2426          fflush_unlocked (&sv->aFiles[i]);
    25           STREAM_UNLOCK (&sv->aFiles[i]);
     27          STREAM_XCPT_UNLOCK (&sv->aFiles[i]);
    2628        }
     29
     30  STREAM_XCPT_END
     31
    2732  return n;
    2833}
  • src/emx/src/lib/io/fprintf.c

     
    1414  int result;
    1515  void *tb;
    1616
     17  STREAM_XCPT_BEGIN
     18
    1719  va_start (arg_ptr, format);
    18   STREAM_LOCK (stream);
     20  STREAM_XCPT_LOCK (stream);
    1921  if (nbuf (stream))
    2022    _fbuf (stream);
    2123  _tmpbuf (stream, tb);
    2224  result = _output (stream, format, arg_ptr);
    2325  if (_endbuf (stream) != 0)
    2426    result = -1;
    25   STREAM_UNLOCK (stream);
     27  STREAM_XCPT_UNLOCK (stream);
    2628  va_end (arg_ptr);
     29
     30  STREAM_XCPT_END
     31
    2732  return result;
    2833}
  • src/emx/src/lib/io/fputc.c

     
    1616{
    1717    int r;
    1818
    19     STREAM_LOCK(stream);
     19    STREAM_XCPT_BEGIN
     20
     21    STREAM_XCPT_LOCK(stream);
    2022    r = _putc_inline(c, stream);
    21     STREAM_UNLOCK(stream);
     23    STREAM_XCPT_UNLOCK(stream);
     24
     25    STREAM_XCPT_END
     26
    2227    return r;
    2328}
    2429
     
    3136{
    3237    int r;
    3338
    34     STREAM_LOCK(stream);
     39    STREAM_XCPT_BEGIN
     40
     41    STREAM_XCPT_LOCK(stream);
    3542    r = _putc_inline(c, stream);
    36     STREAM_UNLOCK(stream);
     43    STREAM_XCPT_UNLOCK(stream);
     44
     45    STREAM_XCPT_END
     46
    3747    return r;
    3848}
  • src/emx/src/lib/io/fread.c

     
    1313
    1414size_t _STD(fread)(void *buffer, size_t size, size_t count, FILE *stream)
    1515{
    16     STREAM_LOCK(stream);
    17     size_t cb = fread_unlocked(buffer, size, count, stream);
    18     STREAM_UNLOCK(stream);
     16    size_t cb;
     17
     18    STREAM_XCPT_BEGIN
     19
     20    STREAM_XCPT_LOCK(stream);
     21    cb = fread_unlocked(buffer, size, count, stream);
     22    STREAM_XCPT_UNLOCK(stream);
     23
     24    STREAM_XCPT_END
     25
    1926    return cb;
    2027}
    2128
  • src/emx/src/lib/io/fscanf.c

     
    1313  va_list arg_ptr;
    1414  int result;
    1515
     16  STREAM_XCPT_BEGIN
     17
    1618  va_start (arg_ptr, format);
    17   STREAM_LOCK (stream);
     19  STREAM_XCPT_LOCK (stream);
    1820  result = _input (stream, format, arg_ptr);
    19   STREAM_UNLOCK (stream);
     21  STREAM_XCPT_UNLOCK (stream);
    2022  va_end (arg_ptr);
     23
     24  STREAM_XCPT_END
     25
    2126  return result;
    2227}
  • src/emx/src/lib/io/fseek.c

     
    182182{
    183183    int result;
    184184
    185     STREAM_LOCK (stream);
     185    STREAM_XCPT_BEGIN
     186
     187    STREAM_XCPT_LOCK (stream);
    186188    result = _fseek_unlocked (stream, offset, origin);
    187     STREAM_UNLOCK (stream);
     189    STREAM_XCPT_UNLOCK (stream);
     190
     191    STREAM_XCPT_END
     192
    188193    return result;
    189194}
    190195
  • src/emx/src/lib/io/ftell.c

     
    102102{
    103103  off_t off;
    104104
    105   STREAM_LOCK (stream);
     105  STREAM_XCPT_BEGIN
     106
     107  STREAM_XCPT_LOCK (stream);
    106108  off = _ftello_unlocked (stream);
    107   STREAM_UNLOCK (stream);
     109  STREAM_XCPT_UNLOCK (stream);
     110
     111  STREAM_XCPT_END
     112
    108113  return off;
    109114}
    110115
  • src/emx/src/lib/io/fwide.c

     
    4848    LIBCLOG_ENTER("pStream=%p iOrientation=%d\n", (void *)pStream, iOrientation);
    4949    int iRet = -1;
    5050#if 0 /** @todo LIBC07 */
    51     STREAM_LOCK(pStream);
     51    STREAM_XCPT_BEGIN
     52    STREAM_XCPT_LOCK(pStream);
    5253    if (iOrientation != 0 && pStream->__iOrientation == 0)
    5354        pStream->__iOrientation = iOrientation > 0 ? 1 : -1;
    5455    iRet =  pStream->__iOrientation;
    55     STREAM_UNLOCK(pStream);
     56    STREAM_XCPT_UNLOCK(pStream);
     57    STREAM_XCPT_END
    5658#endif
    5759    LIBCLOG_RETURN_INT(iRet);
    5860}
  • src/emx/src/lib/io/fwrite.c

     
    168168{
    169169  size_t r;
    170170
    171   STREAM_LOCK (stream);
     171  STREAM_XCPT_BEGIN
     172
     173  STREAM_XCPT_LOCK (stream);
    172174  r = fwrite_unlocked (buffer, size, count, stream);
    173   STREAM_UNLOCK (stream);
     175  STREAM_XCPT_UNLOCK (stream);
     176
     177  STREAM_XCPT_END
     178
    174179  return r;
    175180}
  • src/emx/src/lib/io/getdelim.c

     
    7676        *pcchString = 128;
    7777    }
    7878
    79     /*
    80      * Lock the stream and start reading.
    81      */
    82     STREAM_LOCK(pStream);
    8379    ssize_t rc = 0;
    8480    char *psz = *ppszString;
    8581    char *pszEnd = psz + *pcchString - 1;
     82
     83    STREAM_XCPT_BEGIN
     84
     85    /*
     86     * Lock the stream and start reading.
     87     */
     88    STREAM_XCPT_LOCK(pStream);
    8689    for (;;)
    8790    {
    8891        /** @todo this can be done faster by accessing what's in the buffer directly.
     
    117120        if (ch == chDelim)
    118121            break;
    119122    }
    120     STREAM_UNLOCK(pStream);
     123    STREAM_XCPT_UNLOCK(pStream);
     124
     125    STREAM_XCPT_END
    121126
    122127    if (!rc)
    123128        rc = psz - *ppszString;
  • src/emx/src/lib/io/gets.c

     
    3636
    3737char *_STD(gets)(char *buffer)
    3838{
    39     STREAM_LOCK(stdin);
    40     char *psz = gets_unlocked(buffer);
    41     STREAM_UNLOCK(stdin);
     39    char *psz;
     40
     41    STREAM_XCPT_BEGIN
     42
     43    STREAM_XCPT_LOCK(stdin);
     44    psz = gets_unlocked(buffer);
     45    STREAM_XCPT_UNLOCK(stdin);
     46
     47    STREAM_XCPT_END
     48
    4249    return psz;
    4350}
    4451
  • src/emx/src/lib/io/printf.c

     
    1414  int result;
    1515  void *tb;
    1616
     17  STREAM_XCPT_BEGIN
     18
    1719  va_start (arg_ptr, format);
    18   STREAM_LOCK (stdout);
     20  STREAM_XCPT_LOCK (stdout);
    1921  if (nbuf (stdout))
    2022    _fbuf (stdout);
    2123  _tmpbuf (stdout, tb);
    2224  result = _output (stdout, format, arg_ptr);
    2325  if (_endbuf (stdout) != 0)
    2426    result = -1;
    25   STREAM_UNLOCK (stdout);
     27  STREAM_XCPT_UNLOCK (stdout);
    2628  va_end (arg_ptr);
     29
     30  STREAM_XCPT_END
     31
    2732  return result;
    2833}
  • src/emx/src/lib/io/puts.c

     
    1111
    1212int _STD(puts) (const char *string)
    1313{
    14     STREAM_LOCK(stdout);
    15     int rc = puts_unlocked(string);
    16     STREAM_UNLOCK(stdout);
     14    int rc;
     15
     16    STREAM_XCPT_BEGIN
     17   
     18    STREAM_XCPT_LOCK(stdout);
     19    rc = puts_unlocked(string);
     20    STREAM_XCPT_UNLOCK(stdout);
     21   
     22    STREAM_XCPT_END
     23   
    1724    return rc;
    1825}
    1926
  • src/emx/src/lib/io/rewind.c

     
    99
    1010void _STD(rewind) (FILE *stream)
    1111{
    12   STREAM_LOCK (stream);
     12  STREAM_XCPT_BEGIN
     13  STREAM_XCPT_LOCK (stream);
    1314  fflush_unlocked (stream);
    1415  _fseek_unlocked (stream, 0, SEEK_SET);
    1516  stream->_flags &= ~_IOERR;
    16   STREAM_UNLOCK (stream);
     17  STREAM_XCPT_UNLOCK (stream);
     18  STREAM_XCPT_END
    1719}
  • src/emx/src/lib/io/scanf.c

     
    1313  va_list arg_ptr;
    1414  int result;
    1515
     16  STREAM_XCPT_BEGIN
     17
    1618  va_start (arg_ptr, format);
    17   STREAM_LOCK (stdin);
     19  STREAM_XCPT_LOCK (stdin);
    1820  result = _input (stdin, format, arg_ptr);
    19   STREAM_UNLOCK (stdin);
     21  STREAM_XCPT_UNLOCK (stdin);
    2022  va_end (arg_ptr);
     23
     24  STREAM_XCPT_END
     25
    2126  return result;
    2227}
  • src/emx/src/lib/io/setvbuf.c

     
    1313      || (mode != _IONBF && mode != _IOFBF && mode != _IOLBF))
    1414    return EOF;
    1515
    16   STREAM_LOCK (stream);
     16  STREAM_XCPT_BEGIN
     17
     18  STREAM_XCPT_LOCK (stream);
    1719  fflush_unlocked (stream);
    1820  if ((stream->_flags & _IOBUFMASK) == _IOBUFLIB)
    1921    free (stream->_buffer);
     
    4850      buffer = malloc (size);
    4951      if (buffer == NULL)
    5052        {
    51           STREAM_UNLOCK (stream);
     53          STREAM_XCPT_UNLOCK_END (stream);
    5254          return EOF;
    5355        }
    5456      stream->_buf_size = size;
     
    5860  stream->_ptr = stream->_buffer;
    5961  stream->_rcount = 0;
    6062  stream->_wcount = 0;
    61   STREAM_UNLOCK (stream);
     63  STREAM_XCPT_UNLOCK (stream);
     64
     65  STREAM_XCPT_END
     66
    6267  return 0;
    6368}
  • src/emx/src/lib/io/ungetc.c

     
    153153{
    154154  int result;
    155155
    156   STREAM_LOCK (stream);
     156  STREAM_XCPT_BEGIN
     157
     158  STREAM_XCPT_LOCK (stream);
    157159  result = _ungetc_nolock (c, stream);
    158   STREAM_UNLOCK (stream);
     160  STREAM_XCPT_UNLOCK (stream);
     161
     162  STREAM_XCPT_END
     163
    159164  return result;
    160165}
  • src/emx/src/lib/io/vfprintf.c

     
    1212  int result;
    1313  void *tb;
    1414
    15   STREAM_LOCK (stream);
     15  STREAM_XCPT_BEGIN
     16
     17  STREAM_XCPT_LOCK (stream);
    1618  if (nbuf (stream))
    1719    _fbuf (stream);
    1820  _tmpbuf (stream, tb);
    1921  result = _output (stream, format, arg_ptr);
    2022  if (_endbuf (stream) != 0)
    2123    result = -1;
    22   STREAM_UNLOCK (stream);
     24  STREAM_XCPT_UNLOCK (stream);
     25
     26  STREAM_XCPT_END
     27
    2328  return result;
    2429}
  • src/emx/src/lib/io/vfscanf.c

     
    1212{
    1313  int r;
    1414
    15   STREAM_LOCK (stream);
     15  STREAM_XCPT_BEGIN
     16
     17  STREAM_XCPT_LOCK (stream);
    1618  r = _input (stream, format, arg_ptr);
    17   STREAM_UNLOCK (stream);
     19  STREAM_XCPT_UNLOCK (stream);
     20
     21  STREAM_XCPT_END
     22
    1823  return r;
    1924}
  • src/emx/src/lib/io/vprintf.c

     
    1212  int result;
    1313  void *tb;
    1414
    15   STREAM_LOCK (stdout);
     15  STREAM_XCPT_BEGIN
     16
     17  STREAM_XCPT_LOCK (stdout);
    1618  if (nbuf (stdout))
    1719    _fbuf (stdout);
    1820  _tmpbuf (stdout, tb);
    1921  result = _output (stdout, format, arg_ptr);
    2022  if (_endbuf (stdout) != 0)
    2123    result = -1;
    22   STREAM_UNLOCK (stdout);
     24  STREAM_XCPT_UNLOCK (stdout);
     25
     26  STREAM_XCPT_END
     27
    2328  return result;
    2429}
  • src/emx/src/lib/io/vscanf.c

     
    1212{
    1313  int r;
    1414
    15   STREAM_LOCK (stdin);
     15  STREAM_XCPT_BEGIN
     16
     17  STREAM_XCPT_LOCK (stdin);
    1618  r = _input (stdin, format, arg_ptr);
    17   STREAM_UNLOCK (stdin);
     19  STREAM_XCPT_UNLOCK (stdin);
     20
     21  STREAM_XCPT_END
     22
    1823  return r;
    1924}