[Prev][Next][Index][Thread]
interrupted socket write() due to SIGCHLD (black bars on generated GIFs)
We have a cgi-bin program which generates arbitrarily large GIF files.
Once the GIF files exceed the bufferable limit (~52KB), there is a
race condition where the HTTP Daemon is attempting to write the output
of the CGI program down the HTTP socket (to the browser) and the CGI
program is finishing up.
If you're unlucky, the CGI program finishes while the HTTP Daemon is
still writing data. This causes a SIGCHLD interrupt in the Daemon,
which interrupts the write(2) call in
Library/Implementation/HTWriter.c, causing the write() call to return
-1. At this point, the old code merely (silently, unless in verbose
mode) gives up writing the rest of the CGI program's output to the
client.
This leads to a syndrome we have affectionately termed ``the black
bar'' problem, since the resulting GIF usually ends up blanked black
on the end-user's screen.
We have noticed this when running the HTTP Daemon on Digital Unix (DEC
OSF/1 2.0 & 3.2c), but not on Solaris 2.4 (probably because the
default behavior for an interrupted empty write() call on Solaris is
to restart the write).
The patch below simply checks errno for EINTR (i.e. the write call was
interrupted), and resets the status to zero (i.e. no bytes were
actually written), which permits the while loops to continue to flush
the data down the socket.
(The NCSA HTTPd had a similar problem -- they did check for EINTR ==
errno, but they failed to set the byte count to zero, causing them to
step back a byte in their read buffer!)
(This diff is against the library that was included with the
w3c-httpd-3.0A.tar file:)
----------------------------------------------------------------------
*** HTWriter.c Fri Jul 5 11:01:42 EDT 1996
--- HTWriter.c.ORIG Fri Jul 5 10:56:44 EDT 1996
***************
*** 8,15 ****
#include "HTUtils.h"
#include "tcp.h"
- #include <errno.h> /* for extern int errno */
- #include <strings.h> /* for strerror() */
/* HTML Object
** -----------
--- 8,13 ----
***************
*** 46,52 ****
#endif
while (read_pointer < write_pointer) {
int status;
- errno = 0;
#ifdef OLD_CODE
status = NETWRITE(me->soc, me->buffer, /* Put timeout? @@@ */
write_pointer - read_pointer);
--- 44,49 ----
***************
*** 53,68 ****
#endif /* OLD_CODE */
status = NETWRITE(me->soc, read_pointer, write_pointer - read_pointer);
if (status<0) {
! if (EINTR == errno) {
! status = 0; /* assume the write was interrupted,
! and no bytes were written */
! }
! else {
! if(TRACE) fprintf(stderr,
! "HTWrite: Error: write() on socket returns %d (errno %d -- ``%s''!!!\n",
! status, errno, strerror(errno));
! return;
! }
}
read_pointer += status;
}
--- 50,58 ----
#endif /* OLD_CODE */
status = NETWRITE(me->soc, read_pointer, write_pointer - read_pointer);
if (status<0) {
! if(TRACE) fprintf(stderr,
! "HTWrite: Error: write() on socket returns %d !!!\n", status);
! return;
}
read_pointer += status;
}
***************
*** 120,141 ****
}
#endif
while (read_pointer < write_pointer) {
! int status;
!
! errno = 0;
! status = NETWRITE(me->soc, read_pointer,
! write_pointer - read_pointer);
if (status<0) {
! if (EINTR == errno) {
! status = 0; /* assume the write was interrupted,
! and no bytes were written */
! }
! else {
! if(TRACE) fprintf(stderr,
! "HTWriter_write: Error on socket output stream!!! (errno %d -- ``%s''\n",
! errno, strerror(errno));
! return;
! }
}
read_pointer = read_pointer + status;
}
--- 110,121 ----
}
#endif
while (read_pointer < write_pointer) {
! int status = NETWRITE(me->soc, read_pointer,
! write_pointer - read_pointer);
if (status<0) {
! if(TRACE) fprintf(stderr,
! "HTWriter_write: Error on socket output stream!!!\n");
! return;
}
read_pointer = read_pointer + status;
}
----------------------------------------------------------------------
Permission form:
----------------------------------------------------------------------
Corrections, Modifications, and Patches
Corrections, modifications, patches and the like will not be
incorporated into the W3C software distributions unless accompanied by
the following statement:
MIT is hereby permitted to distribute these contributions as part of its
W3C software distributions at no cost to MIT or its licensed users.
I the undersigned represent that I either own the copyright, or have the
authority to grant these rights:
Name Michael J. McInerny
Title Sr. Systems Designer
Signature ___________________________________
(Michael J. McInerny)
Date ___________________________________
(7/5/96)
Until further notice, please print, sign and send by postal mail to the
following address:
World-Wide Web Consortium
LCS/MIT 545 Technology Square
Cambridge, MA 02139
USA
----------------------------------------------------------------------
Michael McInerny
Sr. System Designer
CLARITECH Corporation
Suite 200A
319 S. Craig St.
Pittsburgh, PA 15213-3726
ph. +1.412.621.0570
fax +1.412.621.0569
e-mail mcinerny@clarit.com