jim 98/05/03 10:17:01
Modified: . STATUS src CHANGES src/include httpd.h src/main http_log.c http_main.c Log: Submitted by: Jim Jagielski Reviewed by: Dean Gaudet, Ralf Engelschall If a child exits with a status of APEXIT_CHILDFATAL, the main httpd process will see this as a "things are totally hosed" and do a server abort, shutting down completely. This is to prevent situations where child errors prevent the server from running correctly and filling the logs up with messages. Revision Changes Path 1.355 +2 -8 apache-1.3/STATUS Index: STATUS =================================================================== RCS file: /export/home/cvs/apache-1.3/STATUS,v retrieving revision 1.354 retrieving revision 1.355 diff -u -r1.354 -r1.355 --- STATUS 1998/05/03 16:46:47 1.354 +++ STATUS 1998/05/03 17:16:56 1.355 @@ -83,6 +83,8 @@ * Ben's WIN32: Extensive overhaul of the way UNCs are handled. * Ralf's fix for referer/agent log entries in installed httpd.conf, PR#2175 * Jim's fix for MIME type case sensitivity disparity, PR#2112 + * Child processes can now "signal" to the parent process that + it (the parent process) should abort, shutting down the server. Available Patches: @@ -147,14 +149,6 @@ errors. The respective flush_funcs also need to be exercised. o Jim's looked over the ap_snprintf() stuff (the changes that Dean did to make thread-safe) and they look fine. - - * The fatal errors that the children detect and fill up the log with - (such as bogus group id) need to be stopped. The proposed fix is to - make the child exit with a special code when a fatal error occurs; the - parent would then abort. See - <[EMAIL PROTECTED]> - [PATCH] <[EMAIL PROTECTED]> - Status: Jim, Dean +1, Ralf +1 * The DoS issue about symlinks to /dev/zero is still present. A device checker patch had been sent to the list a while ago. 1.811 +5 -0 apache-1.3/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.810 retrieving revision 1.811 diff -u -r1.810 -r1.811 --- CHANGES 1998/05/03 16:46:48 1.810 +++ CHANGES 1998/05/03 17:16:57 1.811 @@ -1,5 +1,10 @@ Changes with Apache 1.3b7 + *) Child processes can now "signal" (by exiting with a status + of APEXIT_CHILDFATAL) the parent process to abort and + shutdown the server if the error in the child process was + fatal enough. [Jim Jagielski] + *) mod_autoindex's find_itme() was sensitive to MIME type case. [Jim Jagielski] PR#2112 1.207 +21 -0 apache-1.3/src/include/httpd.h Index: httpd.h =================================================================== RCS file: /export/home/cvs/apache-1.3/src/include/httpd.h,v retrieving revision 1.206 retrieving revision 1.207 diff -u -r1.206 -r1.207 --- httpd.h 1998/04/19 20:10:45 1.206 +++ httpd.h 1998/05/03 17:16:58 1.207 @@ -301,6 +301,27 @@ #endif /* + * Special Apache error codes. These are basically used + * in http_main.c so we can keep track of various errors. + * + * APEXIT_OK: + * A normal exit + * APEXIT_INIT: + * A fatal error arising during the server's init sequence + * APEXIT_CHILDINIT: + * The child died during it's init sequence + * APEXIT_CHILDFATAL: + * A fatal error, resulting in the whole server aborting. + * If a child exits with this error, the parent process + * considers this a server-wide fatal error and aborts. + * + */ +#define APEXIT_OK 0x0 +#define APEXIT_INIT 0x2 +#define APEXIT_CHILDINIT 0x3 +#define APEXIT_CHILDFATAL 0xf + +/* * (Unix, OS/2 only) * Interval, in microseconds, between scoreboard maintenance. During * each scoreboard maintenance cycle the parent decides if it needs to 1.55 +1 -0 apache-1.3/src/main/http_log.c Index: http_log.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_log.c,v retrieving revision 1.54 retrieving revision 1.55 diff -u -r1.54 -r1.55 --- http_log.c 1998/04/27 22:38:05 1.54 +++ http_log.c 1998/05/03 17:16:59 1.55 @@ -177,6 +177,7 @@ execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL); #endif exit (1); + /* NOT REACHED */ return(child_pid); } 1.329 +51 -40 apache-1.3/src/main/http_main.c Index: http_main.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_main.c,v retrieving revision 1.328 retrieving revision 1.329 diff -u -r1.328 -r1.329 --- http_main.c 1998/05/02 11:15:11 1.328 +++ http_main.c 1998/05/03 17:17:00 1.329 @@ -404,10 +404,10 @@ break; case 0: fprintf(stderr, "didn't get lock\n"); - exit(-1); + clean_child_exit(APEXIT_CHILDFATAL); case -1: perror("ussetlock"); - exit(-1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -415,7 +415,7 @@ { if (usunsetlock(uslock) == -1) { perror("usunsetlock"); - exit(-1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -464,27 +464,27 @@ fd = open("/dev/zero", O_RDWR); if (fd == -1) { perror("open(/dev/zero)"); - exit(1); + exit(APEXIT_INIT); } accept_mutex = (pthread_mutex_t *) mmap((caddr_t) 0, sizeof(*accept_mutex), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (accept_mutex == (void *) (caddr_t) - 1) { perror("mmap"); - exit(1); + exit(APEXIT_INIT); } close(fd); if ((errno = pthread_mutexattr_init(&mattr))) { perror("pthread_mutexattr_init"); - exit(1); + exit(APEXIT_INIT); } if ((errno = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))) { perror("pthread_mutexattr_setpshared"); - exit(1); + exit(APEXIT_INIT); } if ((errno = pthread_mutex_init(accept_mutex, &mattr))) { perror("pthread_mutex_init"); - exit(1); + exit(APEXIT_INIT); } sigfillset(&accept_block_mask); sigdelset(&accept_block_mask, SIGHUP); @@ -499,12 +499,12 @@ if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) { perror("sigprocmask(SIG_BLOCK)"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } if ((err = pthread_mutex_lock(accept_mutex))) { errno = err; perror("pthread_mutex_lock"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } have_accept_mutex = 1; } @@ -516,7 +516,7 @@ if ((err = pthread_mutex_unlock(accept_mutex))) { errno = err; perror("pthread_mutex_unlock"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } /* There is a slight race condition right here... if we were to die right * now, we'd do another pthread_mutex_unlock. Now, doing that would let @@ -584,12 +584,12 @@ sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); if (sem_id < 0) { perror("semget"); - exit(1); + exit(APEXIT_INIT); } ick.val = 1; if (semctl(sem_id, 0, SETVAL, ick) < 0) { perror("semctl(SETVAL)"); - exit(1); + exit(APEXIT_INIT); } if (!getuid()) { /* restrict it to use only by the appropriate user_id ... not that this @@ -601,7 +601,7 @@ ick.buf = &buf; if (semctl(sem_id, 0, IPC_SET, ick) < 0) { perror("semctl(IPC_SET)"); - exit(1); + exit(APEXIT_INIT); } } ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); @@ -619,7 +619,7 @@ { if (semop(sem_id, &op_on, 1) < 0) { perror("accept_mutex_on"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -627,7 +627,7 @@ { if (semop(sem_id, &op_off, 1) < 0) { perror("accept_mutex_off"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -662,7 +662,7 @@ if (lock_fd == -1) { perror("open"); fprintf(stderr, "Cannot open lock file: %s\n", ap_lock_fname); - exit(1); + exit(APEXIT_INIT); } unlink(ap_lock_fname); } @@ -680,7 +680,7 @@ "fcntl: F_SETLKW: Error getting accept lock, exiting! " "Perhaps you need to use the LockFile directive to place " "your lock file on a local disk!"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -696,7 +696,7 @@ "fcntl: F_SETLKW: Error freeing accept lock, exiting! " "Perhaps you need to use the LockFile directive to place " "your lock file on a local disk!"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -720,7 +720,7 @@ if (lock_fd == -1) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "Child cannot open lock file: %s\n", ap_lock_fname); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDINIT); } } @@ -736,7 +736,7 @@ if (lock_fd == -1) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "Parent cannot open lock file: %s\n", ap_lock_fname); - exit(1); + exit(APEXIT_INIT); } ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); } @@ -751,7 +751,7 @@ if (ret < 0) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "flock: LOCK_EX: Error getting accept lock. Exiting!"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -760,7 +760,7 @@ if (flock(lock_fd, LOCK_UN) < 0) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "flock: LOCK_UN: Error freeing accept lock. Exiting!"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } } @@ -1419,7 +1419,7 @@ m = (caddr_t) create_shared_heap("\\SHAREMEM\\SCOREBOARD", SCOREBOARD_SIZE); if (m == 0) { fprintf(stderr, "httpd: Could not create OS/2 Shared memory pool.\n"); - exit(1); + exit(APEXIT_INIT); } rc = _uopen((Heap_t) m); @@ -1438,7 +1438,7 @@ m = (caddr_t) get_shared_heap("\\SHAREMEM\\SCOREBOARD"); if (m == 0) { fprintf(stderr, "httpd: Could not find existing OS/2 Shared memory pool.\n"); - exit(1); + exit(APEXIT_INIT); } rc = _uopen((Heap_t) m); @@ -1488,19 +1488,19 @@ fd = shm_open(ap_scoreboard_fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) { perror("httpd: could not open(create) scoreboard"); - exit(1); + exit(APEXIT_INIT); } if (ltrunc(fd, (off_t) SCOREBOARD_SIZE, SEEK_SET) == -1) { perror("httpd: could not ltrunc scoreboard"); shm_unlink(ap_scoreboard_fname); - exit(1); + exit(APEXIT_INIT); } if ((m = (caddr_t) mmap((caddr_t) 0, (size_t) SCOREBOARD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) 0)) == (caddr_t) - 1) { perror("httpd: cannot mmap scoreboard"); shm_unlink(ap_scoreboard_fname); - exit(1); + exit(APEXIT_INIT); } close(fd); ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup); @@ -1544,7 +1544,7 @@ if (m == (caddr_t) - 1) { perror("mmap"); fprintf(stderr, "httpd: Could not mmap memory\n"); - exit(1); + exit(APEXIT_INIT); } #else /* Sun style */ @@ -1554,14 +1554,14 @@ if (fd == -1) { perror("open"); fprintf(stderr, "httpd: Could not open /dev/zero\n"); - exit(1); + exit(APEXIT_INIT); } m = mmap((caddr_t) 0, SCOREBOARD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (m == (caddr_t) - 1) { perror("mmap"); fprintf(stderr, "httpd: Could not mmap /dev/zero\n"); - exit(1); + exit(APEXIT_INIT); } close(fd); #endif @@ -1594,7 +1594,7 @@ #endif ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "could not call shmget"); - exit(1); + exit(APEXIT_INIT); } ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, @@ -1647,7 +1647,7 @@ shmid); } if (ap_scoreboard_image == BADSHMAT) /* now bailout */ - exit(1); + exit(APEXIT_INIT); #ifdef MOVEBREAK if (obrk == (char *) -1) @@ -1742,7 +1742,7 @@ if (scoreboard_fd == -1) { perror(ap_scoreboard_fname); fprintf(stderr, "Cannot open scoreboard file:\n"); - exit(1); + exit(APEXIT_INIT); } ap_register_cleanup(p, NULL, cleanup_scoreboard_file, ap_null_cleanup); @@ -2507,7 +2507,7 @@ "getpwuid: couldn't determine user name from uid %u, " "you probably need to modify the User directive", (unsigned)uid); - exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } name = ent->pw_name; @@ -2524,20 +2524,20 @@ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "initgroups: unable to set groups for User %s " "and Group %u", name, (unsigned)ap_group_id); - exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } #ifdef MULTIPLE_GROUPS if (getgroups(NGROUPS_MAX, group_id_list) == -1) { ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "getgroups: unable to get group list"); - exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } #endif if (setgid(ap_group_id) == -1) { ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "setgid: unable to set group id to Group %u", (unsigned)ap_group_id); - exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } #endif } @@ -3150,7 +3150,7 @@ if (!geteuid() && setuid(ap_user_id) == -1) { ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "setuid: unable to change uid"); - clean_child_exit(1); + clean_child_exit(APEXIT_CHILDFATAL); } #endif @@ -3823,7 +3823,18 @@ * extra child */ if (pid >= 0) { - /* Child died... note that it's gone in the scoreboard. */ + /* Child died... if it died due to a fatal error, + * we should simply bail out. + */ + if ((WIFEXITED(status)) && + WEXITSTATUS(status) == APEXIT_CHILDFATAL) { + ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, + "Child %d returned a Fatal error... \n" + "Apache is exiting!", + pid); + exit(APEXIT_CHILDFATAL); + } + /* non-fatal death... note that it's gone in the scoreboard. */ ap_sync_scoreboard_image(); child_slot = find_child_by_pid(pid); Explain2("Reaping child %d slot %d", pid, child_slot);