diff options
Diffstat (limited to 'src/child.c')
-rw-r--r-- | src/child.c | 553 |
1 files changed, 281 insertions, 272 deletions
diff --git a/src/child.c b/src/child.c index c4a19b2..eb29a78 100644 --- a/src/child.c +++ b/src/child.c @@ -1,4 +1,4 @@ -/* $Id: child.c,v 1.17 2005-07-12 17:39:43 rjkaes Exp $ +/* $Id: child.c,v 1.18 2005-08-15 03:54:31 rjkaes Exp $ * * Handles the creation/destruction of the various children required for * processing incoming connections. @@ -35,9 +35,9 @@ static socklen_t addrlen; */ enum child_status_t { T_EMPTY, T_WAITING, T_CONNECTED }; struct child_s { - pid_t tid; - unsigned int connects; - enum child_status_t status; + pid_t tid; + unsigned int connects; + enum child_status_t status; }; /* @@ -47,11 +47,11 @@ struct child_s { static struct child_s *child_ptr; static struct child_config_s { - int maxclients, maxrequestsperchild; - int maxspareservers, minspareservers, startservers; + int maxclients, maxrequestsperchild; + int maxspareservers, minspareservers, startservers; } child_config; -static unsigned int* servers_waiting; /* servers waiting for a connection */ +static unsigned int *servers_waiting; /* servers waiting for a connection */ /* * Lock/Unlock the "servers_waiting" variable so that two children cannot @@ -72,40 +72,40 @@ static int lock_fd = -1; static void _child_lock_init(void) { - char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX"; + char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX"; - lock_fd = mkstemp(lock_file); - unlink(lock_file); + lock_fd = mkstemp(lock_file); + unlink(lock_file); - lock_it.l_type = F_WRLCK; - lock_it.l_whence = SEEK_SET; - lock_it.l_start = 0; - lock_it.l_len = 0; + lock_it.l_type = F_WRLCK; + lock_it.l_whence = SEEK_SET; + lock_it.l_start = 0; + lock_it.l_len = 0; - unlock_it.l_type = F_UNLCK; - unlock_it.l_whence = SEEK_SET; - unlock_it.l_start = 0; - unlock_it.l_len = 0; + unlock_it.l_type = F_UNLCK; + unlock_it.l_whence = SEEK_SET; + unlock_it.l_start = 0; + unlock_it.l_len = 0; } static void _child_lock_wait(void) { - int rc; - - while ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) { - if (errno == EINTR) - continue; - else - return; - } + int rc; + + while ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) { + if (errno == EINTR) + continue; + else + return; + } } static void _child_lock_release(void) { - if (fcntl(lock_fd, F_SETLKW, &unlock_it) < 0) - return; + if (fcntl(lock_fd, F_SETLKW, &unlock_it) < 0) + return; } /* END OF LOCKING SECTION */ @@ -131,119 +131,124 @@ _child_lock_release(void) short int child_configure(child_config_t type, int val) { - switch (type) { - case CHILD_MAXCLIENTS: - child_config.maxclients = val; - break; - case CHILD_MAXSPARESERVERS: - child_config.maxspareservers = val; - break; - case CHILD_MINSPARESERVERS: - child_config.minspareservers = val; - break; - case CHILD_STARTSERVERS: - child_config.startservers = val; - break; - case CHILD_MAXREQUESTSPERCHILD: - child_config.maxrequestsperchild = val; - break; - default: - DEBUG2("Invalid type (%d)", type); - return -1; - } - - return 0; + switch (type) { + case CHILD_MAXCLIENTS: + child_config.maxclients = val; + break; + case CHILD_MAXSPARESERVERS: + child_config.maxspareservers = val; + break; + case CHILD_MINSPARESERVERS: + child_config.minspareservers = val; + break; + case CHILD_STARTSERVERS: + child_config.startservers = val; + break; + case CHILD_MAXREQUESTSPERCHILD: + child_config.maxrequestsperchild = val; + break; + default: + DEBUG2("Invalid type (%d)", type); + return -1; + } + + return 0; } /* * This is the main (per child) loop. */ static void -child_main(struct child_s* ptr) +child_main(struct child_s *ptr) { - int connfd; - struct sockaddr *cliaddr; - socklen_t clilen; + int connfd; + struct sockaddr *cliaddr; + socklen_t clilen; - cliaddr = safemalloc(addrlen); - if (!cliaddr) { - log_message(LOG_CRIT, - "Could not allocate memory for child address."); - exit(0); - } + cliaddr = safemalloc(addrlen); + if (!cliaddr) { + log_message(LOG_CRIT, + "Could not allocate memory for child address."); + exit(0); + } - ptr->connects = 0; + ptr->connects = 0; - while (!config.quit) { - ptr->status = T_WAITING; + while (!config.quit) { + ptr->status = T_WAITING; - clilen = addrlen; + clilen = addrlen; - connfd = accept(listenfd, cliaddr, &clilen); + connfd = accept(listenfd, cliaddr, &clilen); #ifndef NDEBUG - /* - * Enable the TINYPROXY_DEBUG environment variable if you - * want to use the GDB debugger. - */ - if (getenv("TINYPROXY_DEBUG")) { - /* Pause for 10 seconds to allow us to connect debugger */ - fprintf(stderr, - "Process has accepted connection: %ld\n", (long int)ptr->tid); - sleep(10); - fprintf(stderr, "Continuing process: %ld\n", (long int)ptr->tid); - } + /* + * Enable the TINYPROXY_DEBUG environment variable if you + * want to use the GDB debugger. + */ + if (getenv("TINYPROXY_DEBUG")) { + /* Pause for 10 seconds to allow us to connect debugger */ + fprintf(stderr, + "Process has accepted connection: %ld\n", + (long int)ptr->tid); + sleep(10); + fprintf(stderr, "Continuing process: %ld\n", + (long int)ptr->tid); + } #endif - /* - * Make sure no error occurred... - */ - if (connfd < 0) { - log_message(LOG_ERR, "Accept returned an error (%s) ... retrying.", strerror(errno)); - continue; - } - - ptr->status = T_CONNECTED; - - SERVER_DEC(); - - handle_connection(connfd); - ptr->connects++; - - if (child_config.maxrequestsperchild != 0) { - DEBUG2("%u connections so far...", ptr->connects); - - if (ptr->connects == child_config.maxrequestsperchild) { - log_message(LOG_NOTICE, - "Child has reached MaxRequestsPerChild (%u). Killing child.", - ptr->connects); - break; - } - } - - SERVER_COUNT_LOCK(); - if (*servers_waiting > child_config.maxspareservers) { - /* - * There are too many spare children, kill ourself - * off. - */ - log_message(LOG_NOTICE, - "Waiting servers (%d) exceeds MaxSpareServers (%d). Killing child.", - *servers_waiting, child_config.maxspareservers); - SERVER_COUNT_UNLOCK(); - - break; - } else { - SERVER_COUNT_UNLOCK(); - } - - SERVER_INC(); - } - - ptr->status = T_EMPTY; - - safefree(cliaddr); - exit(0); + /* + * Make sure no error occurred... + */ + if (connfd < 0) { + log_message(LOG_ERR, + "Accept returned an error (%s) ... retrying.", + strerror(errno)); + continue; + } + + ptr->status = T_CONNECTED; + + SERVER_DEC(); + + handle_connection(connfd); + ptr->connects++; + + if (child_config.maxrequestsperchild != 0) { + DEBUG2("%u connections so far...", ptr->connects); + + if (ptr->connects == child_config.maxrequestsperchild) { + log_message(LOG_NOTICE, + "Child has reached MaxRequestsPerChild (%u). Killing child.", + ptr->connects); + break; + } + } + + SERVER_COUNT_LOCK(); + if (*servers_waiting > child_config.maxspareservers) { + /* + * There are too many spare children, kill ourself + * off. + */ + log_message(LOG_NOTICE, + "Waiting servers (%d) exceeds MaxSpareServers (%d). Killing child.", + *servers_waiting, + child_config.maxspareservers); + SERVER_COUNT_UNLOCK(); + + break; + } else { + SERVER_COUNT_UNLOCK(); + } + + SERVER_INC(); + } + + ptr->status = T_EMPTY; + + safefree(cliaddr); + exit(0); } /* @@ -251,22 +256,22 @@ child_main(struct child_s* ptr) * child_main() function. */ static pid_t -child_make(struct child_s* ptr) +child_make(struct child_s *ptr) { - pid_t pid; - - if ((pid = fork()) > 0) - return pid; /* parent */ - - /* - * Reset the SIGNALS so that the child can be reaped. - */ - set_signal_handler(SIGCHLD, SIG_DFL); - set_signal_handler(SIGTERM, SIG_DFL); - set_signal_handler(SIGHUP, SIG_DFL); - - child_main(ptr); /* never returns */ - return -1; + pid_t pid; + + if ((pid = fork()) > 0) + return pid; /* parent */ + + /* + * Reset the SIGNALS so that the child can be reaped. + */ + set_signal_handler(SIGCHLD, SIG_DFL); + set_signal_handler(SIGTERM, SIG_DFL); + set_signal_handler(SIGHUP, SIG_DFL); + + child_main(ptr); /* never returns */ + return -1; } /* @@ -275,78 +280,80 @@ child_make(struct child_s* ptr) short int child_pool_create(void) { - unsigned int i; - - /* - * Make sure the number of MaxClients is not zero, since this - * variable determines the size of the array created for children - * later on. - */ - if (child_config.maxclients == 0) { - log_message(LOG_ERR, - "child_pool_create: \"MaxClients\" must be greater than zero."); - return -1; - } - if (child_config.startservers == 0) { - log_message(LOG_ERR, - "child_pool_create: \"StartServers\" must be greater than zero."); - return -1; - } - - child_ptr = calloc_shared_memory(child_config.maxclients, - sizeof(struct child_s)); - if (!child_ptr) { - log_message(LOG_ERR, "Could not allocate memory for children."); - return -1; - } - - servers_waiting = malloc_shared_memory(sizeof(unsigned int)); - if (servers_waiting == MAP_FAILED) { - log_message(LOG_ERR, "Could not allocate memory for child counting."); - return -1; - } - *servers_waiting = 0; - - /* - * Create a "locking" file for use around the servers_waiting - * variable. - */ - _child_lock_init(); - - if (child_config.startservers > child_config.maxclients) { - log_message(LOG_WARNING, - "Can not start more than \"MaxClients\" servers. Starting %u servers instead.", - child_config.maxclients); - child_config.startservers = child_config.maxclients; - } - - for (i = 0; i != child_config.maxclients; i++) { - child_ptr[i].status = T_EMPTY; - child_ptr[i].connects = 0; - } - - for (i = 0; i != child_config.startservers; i++) { - DEBUG2("Trying to create child %d of %d", i + 1, child_config.startservers); - child_ptr[i].status = T_WAITING; - child_ptr[i].tid = child_make(&child_ptr[i]); - - if (child_ptr[i].tid < 0) { - log_message(LOG_WARNING, - "Could not create child number %d of %d", - i, child_config.startservers); - return -1; - } else { - log_message(LOG_INFO, - "Creating child number %d of %d ...", - i + 1, child_config.startservers); - - SERVER_INC(); - } - } - - log_message(LOG_INFO, "Finished creating all children."); - - return 0; + unsigned int i; + + /* + * Make sure the number of MaxClients is not zero, since this + * variable determines the size of the array created for children + * later on. + */ + if (child_config.maxclients == 0) { + log_message(LOG_ERR, + "child_pool_create: \"MaxClients\" must be greater than zero."); + return -1; + } + if (child_config.startservers == 0) { + log_message(LOG_ERR, + "child_pool_create: \"StartServers\" must be greater than zero."); + return -1; + } + + child_ptr = calloc_shared_memory(child_config.maxclients, + sizeof(struct child_s)); + if (!child_ptr) { + log_message(LOG_ERR, "Could not allocate memory for children."); + return -1; + } + + servers_waiting = malloc_shared_memory(sizeof(unsigned int)); + if (servers_waiting == MAP_FAILED) { + log_message(LOG_ERR, + "Could not allocate memory for child counting."); + return -1; + } + *servers_waiting = 0; + + /* + * Create a "locking" file for use around the servers_waiting + * variable. + */ + _child_lock_init(); + + if (child_config.startservers > child_config.maxclients) { + log_message(LOG_WARNING, + "Can not start more than \"MaxClients\" servers. Starting %u servers instead.", + child_config.maxclients); + child_config.startservers = child_config.maxclients; + } + + for (i = 0; i != child_config.maxclients; i++) { + child_ptr[i].status = T_EMPTY; + child_ptr[i].connects = 0; + } + + for (i = 0; i != child_config.startservers; i++) { + DEBUG2("Trying to create child %d of %d", i + 1, + child_config.startservers); + child_ptr[i].status = T_WAITING; + child_ptr[i].tid = child_make(&child_ptr[i]); + + if (child_ptr[i].tid < 0) { + log_message(LOG_WARNING, + "Could not create child number %d of %d", + i, child_config.startservers); + return -1; + } else { + log_message(LOG_INFO, + "Creating child number %d of %d ...", + i + 1, child_config.startservers); + + SERVER_INC(); + } + } + + log_message(LOG_INFO, "Finished creating all children."); + + return 0; } /* @@ -356,59 +363,61 @@ child_pool_create(void) void child_main_loop(void) { - unsigned int i; - - while (1) { - if (config.quit) - return; - - /* If there are not enough spare servers, create more */ - SERVER_COUNT_LOCK(); - if (*servers_waiting < child_config.minspareservers) { - log_message(LOG_NOTICE, - "Waiting servers (%d) is less than MinSpareServers (%d). Creating new child.", - *servers_waiting, child_config.minspareservers); - - SERVER_COUNT_UNLOCK(); - - for (i = 0; i != child_config.maxclients; i++) { - if (child_ptr[i].status == T_EMPTY) { - child_ptr[i].status = T_WAITING; - child_ptr[i].tid = child_make(&child_ptr[i]); - if (child_ptr[i].tid < 0) { - log_message(LOG_NOTICE, - "Could not create child"); - - child_ptr[i].status = T_EMPTY; - break; - } - - SERVER_INC(); - - break; - } - } - } else { - SERVER_COUNT_UNLOCK(); - } - - sleep(5); - - /* Handle log rotation if it was requested */ - if (received_sighup) { - truncate_log_file(); + unsigned int i; + + while (1) { + if (config.quit) + return; + + /* If there are not enough spare servers, create more */ + SERVER_COUNT_LOCK(); + if (*servers_waiting < child_config.minspareservers) { + log_message(LOG_NOTICE, + "Waiting servers (%d) is less than MinSpareServers (%d). Creating new child.", + *servers_waiting, + child_config.minspareservers); + + SERVER_COUNT_UNLOCK(); + + for (i = 0; i != child_config.maxclients; i++) { + if (child_ptr[i].status == T_EMPTY) { + child_ptr[i].status = T_WAITING; + child_ptr[i].tid = + child_make(&child_ptr[i]); + if (child_ptr[i].tid < 0) { + log_message(LOG_NOTICE, + "Could not create child"); + + child_ptr[i].status = T_EMPTY; + break; + } + + SERVER_INC(); + + break; + } + } + } else { + SERVER_COUNT_UNLOCK(); + } + + sleep(5); + + /* Handle log rotation if it was requested */ + if (received_sighup) { + truncate_log_file(); #ifdef FILTER_ENABLE - if (config.filter) { - filter_destroy(); - filter_init(); - } - log_message(LOG_NOTICE, "Re-reading filter file."); -#endif /* FILTER_ENABLE */ - - received_sighup = FALSE; - } - } + if (config.filter) { + filter_destroy(); + filter_init(); + } + log_message(LOG_NOTICE, "Re-reading filter file."); +#endif /* FILTER_ENABLE */ + + received_sighup = FALSE; + } + } } /* @@ -417,23 +426,23 @@ child_main_loop(void) void child_kill_children(void) { - unsigned int i; - - for (i = 0; i != child_config.maxclients; i++) { - if (child_ptr[i].status != T_EMPTY) - kill(child_ptr[i].tid, SIGTERM); - } + unsigned int i; + + for (i = 0; i != child_config.maxclients; i++) { + if (child_ptr[i].status != T_EMPTY) + kill(child_ptr[i].tid, SIGTERM); + } } int child_listening_sock(uint16_t port) { - listenfd = listen_sock(port, &addrlen); - return listenfd; + listenfd = listen_sock(port, &addrlen); + return listenfd; } void child_close_sock(void) { - close(listenfd); + close(listenfd); } |