summaryrefslogtreecommitdiff
path: root/src/child.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/child.c')
-rw-r--r--src/child.c553
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);
}