Message-Id: <199609212046.NAA07075@taz.hyperreal.com> From: yulpgi@odyssee.net To: chuck@wormhole.telebase.com Date: Sat Sep 21 13:46:52 1996 Subject: WWW Form Bug Report: "standalone stops serving, after repeated reloads from browser" on UnixWare Submitter: yulpgi@odyssee.net Operating system: UnixWare, version: 2.01 Version of Apache Used: 1.1.1 Extra Modules used: see below Configuration URL exhibiting problem: my site is only available when i logon to my isp Symptoms: -- I'm assuming that the way the program is compiled and linked is enough to find out the configuration. There is on the http_main.c shown here but all modules were compiled with the same switches. cc -c -O2 -DSVR4 -DNEED_LINGER -DSTATUS http_main.c cc -o httpd alloc.o http_main.o http_core.o http_config.o http_request .o http_log.o http_protocol.o rfc1413.o util.o util_script.o modules.o buff.o m d5c.o util_md5.o explain.o http_bprintf.o mod_mime.o mod_access.o mod_auth.o mod_negotiation.o mod_include.o mod_dir.o mod_cgi.o mod_userdir.o mod_alias .o mod_env.o mod_log_common.o mod_asis.o mod_imap.o mod_actions.o mod_stat us.o mod_info.o mod_cookies.o -lsocket -lnsl -lcrypt # I sent some e-mail to dan@dpcsys.com before I realised you had a bug report form. This is the message I sent. I just writing this to you to let you know that I've loaded the binaries that you so kindly furnished to apache.org. Unfortunenately there seems to be 2 real big problems. Not your fault I've recompiled myself and these problems are still evident. My setup: Unixware 2.01 16mb memory Browser Netscape 2.01Gold, win95, 32bit 1. Server ceases to respond in Standalone Mode I ran across this problem because when testing a page, I would set the browser's mem and disk cache to zero. Then reload to see the results. Try this on your server, make sure no one is using the server. In Netscape (my version 2.01Gold) set the memory and disk cache to zero. Then start bringing up the same page by repeated click on RELOAD, not even waiting for the page to completely load. It won't be long before the server will stop sending pages. I tried resetting the first occurance of httpd (the one whose parent is pid 1) using HUP which forces the server to reload the configuration. This was confirmed in access-log or error-log cannot remember. That didn't help. Another side effect is that you cannot kill the server daemons either. Only recourse is to reboot the whole system. So I decided to try the other method of using the server, albeit creating more of a load on the system. The following is another problem that occurs. Core Dump for every invocation of httpd using inetd method. When the server is invoked by inetd, there will be a core dump for each invocation in /etc/saf/inetd directory. This happens when the server has finished sending a page and a timer to keep it alive has run out. I only noticed this after using the server for 3 months. I started running out of space in my root directory. So I started to look around in http_main.c and found out that the section of code causing the problem is in timeout() function which is called as a result of an alarm setup in the hard_timeout function which is called from read_request. I don't know how to use a debugger, so I changed this statement in inetd.conf. http stream tcp nowait root /opt/lib/apache/httpd-debug httpd httpd-debug is simply a script redirecting stderror to a log file. #!/bin/sh /opt/lib/apache/httpd httpd 2>> /tmp/httpd-log timeout(sig) is called as a result of an alarm that is setup in hard_timeout. I placed printf statements in different parts of the code to see how far it would get. I've narrowed it down to one variable current_conn if the server is not being used in standalone. Based on which signal and which type read in this case, There is cleaning up that goes on. void timeout(sig) /* Also called on SIGPIPE */ int sig; { char errstr[MAX_STRING_LEN]; void *dirconf; fprintf(stderr, "In timeout routine\n"); signal(SIGPIPE, SIG_IGN); /* Block SIGPIPE */ if (alarms_blocked) { alarm_pending = 1; return; } fprintf(stderr, "In timeout routine, before siglongjmp\n"); if (!current_conn) { fprintf(stderr, "In timeout routine, in siglongjmp\n"); #ifdef NEXT longjmp(jmpbuffer,1); #else siglongjmp(jmpbuffer,1); #endif } fprintf(stderr, "In timeout routine, after siglongjmp\n"); if (timeout_req != NULL) dirconf = timeout_req->per_dir_config; else dirconf = current_conn->server->lookup_defaults; fprintf(stderr, "In timeout routine, after if timeout_req != NULL\n"); if (sig == SIGPIPE) { sprintf(errstr,"%s lost connection to client %s", timeout_name ? timeout_name : "request", get_remote_host(current_conn, dirconf, REMOTE_NAME)); } else { sprintf(errstr,"%s timed out for %s", timeout_name ? timeout_name : "request", get_remote_host(current_conn, dirconf, REMOTE_NAME)); } fprintf(stderr,"In timeout routine, after sig test for SIGPIPE\n"); if (!current_conn->keptalive) log_error(errstr, current_conn->server); fprintf(stderr, "In timeout routine, after current_conn-keptalive\n"); if (timeout_req) { /* Someone has asked for this transaction to just be aborted * if it times out... */ request_rec *log_req = timeout_req; while (log_req->main || log_req->prev) { /* Get back to original request... */ if (log_req->main) log_req = log_req->main; else log_req = log_req->prev; } if (!current_conn->keptalive) log_transaction(log_req); fprintf(stderr, "Just before bclose in timeout code\n"); bclose(timeout_req->connection->client); fprintf(stderr, "Just after bclose in timeout code\n"); if (!standalone) exit(0); #ifdef NEXT longjmp(jmpbuffer,1); #else siglongjmp(jmpbuffer,1); #endif } else { abort_connection (current_conn); } } /* end of code segment for mail Output from /tmp/httpd-log # cat httpd-log In timeout routine In timeout routine, before siglongjmp In timeout routine, in siglongjmp In timeout routine, after siglongjmp In timeout routine, after if timeout_req != NULL # as we can see it never gets past this code. I think it because current_conn is undefined. if (sig == SIGPIPE) { sprintf(errstr,"%s lost connection to client %s", timeout_name ? timeout_name : "request", get_remote_host(current_conn, dirconf, REMOTE_NAME)); } else { sprintf(errstr,"%s timed out for %s", timeout_name ? timeout_name : "request", get_remote_host(current_conn, dirconf, REMOTE_NAME)); } I couldn't find a place were it is loaded if the server is running using the inetd method of starting it. That loop is confined to a small area of code in the main() part of the program. I don't program in C I was just wondering if you're having similar problems. I thought I would this to you before it becomes a big problem if your using the server in commercial setting. In closing I hope that this info can be useful to someone who is more qualified than I to fix the problem. This code is also used for standalone mode, an I think that repeated reloads are causing broken pipes at a high rate, are confusing the timeout(sig) function. -- Backtrace: -- Don't gdb or dbx not part of UnixWare. -- chuck Chuck Murcko N2K Inc. Wayne PA chuck@telebase.com And now, on a lighter note: Life would be so much easier if we could just look at the source code.