- From: Michael J. McInerny <mcinerny@clarit.com>
- Date: Fri, 5 Jul 1996 11:32:40 -0400
- To: www-lib-bugs@w3.org
- Cc: mcinerny@clarit.com
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
Received on Friday, 5 July 1996 11:29:55 UTC