On Fri, Jun 15, 2007 at 06:47:55PM +0200, Pierre Habouzit wrote: > Nothing in POSIX says what happens wrt to fwrite and signals. At least > it's very unclear. But indeed the fact that SA_RESTART is the default > value for linux does not seem to be a POSIX requirement either.
I have studied the source today, and it turned out that the problem is not signal specific, but how glibc treats any error on writing. Unfortunately, it loses all data stored in the buffer. Probably, it does not matter for fatal errors, because you will not able to write more anyway, but for recoverable errors like EINTR or ENOSPC, it is not a smart thing to do. Here is a small patch that corrects this problem: --- glibc-2.3.6/libio/fileops.c.orig 2004-12-07 01:36:56.000000000 +0300 +++ glibc-2.3.6/libio/fileops.c 2007-06-18 12:29:50.739890036 +0400 @@ -516,10 +516,19 @@ new_do_write (fp, data, to_do) fp->_cur_column = INTUSE(_IO_adjust_column) (fp->_cur_column - 1, data, count) + 1; _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); - fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base; - fp->_IO_write_end = (fp->_mode <= 0 + if (__builtin_expect (count == to_do, 1)) + { + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base; + fp->_IO_write_end = (fp->_mode <= 0 && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) ? fp->_IO_buf_base : fp->_IO_buf_end); + } + else if (count > 0 && fp->_IO_write_base == data) + { + memmove (data, data+count, + fp->_IO_write_ptr - fp->_IO_write_base - count); + fp->_IO_write_ptr -= count; + } return count; } The patch does not change the behavior of new_do_write in the case of success, but when an error happens, I do not emptify the output buffer. In fact, in the case when data were partly written (count>0) and data were from the output buffer (fp->_IO_write_base == data), I remove written data from the buffer and adjust the write pointer accordingly. Warning: I have not tested this patch, but it seems trivial, so I hope it works. Also, I should note that though this patch prevents losing buffer on error, it does not prevent the possibility that fputs can return an error, while a part of the given string was written, but it is restriction of the interface. So using fputs with non-restartable signals is not a good idea anyway, still fwrite can be used in this way for writing bytes if this bug with losing data in buffer is fixed. Thanks, Dmitry -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]