summaryrefslogtreecommitdiff
path: root/src/child.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/child.c')
-rw-r--r--src/child.c611
1 files changed, 319 insertions, 292 deletions
diff --git a/src/child.c b/src/child.c
index 1bb1802..25b95b8 100644
--- a/src/child.c
+++ b/src/child.c
@@ -37,11 +37,13 @@ static socklen_t addrlen;
/*
* Stores the internal data needed for each child (connection)
*/
-enum child_status_t { T_EMPTY, T_WAITING, T_CONNECTED };
-struct child_s {
- pid_t tid;
- unsigned int connects;
- enum child_status_t status;
+enum child_status_t
+{ T_EMPTY, T_WAITING, T_CONNECTED };
+struct child_s
+{
+ pid_t tid;
+ unsigned int connects;
+ enum child_status_t status;
};
/*
@@ -50,12 +52,13 @@ struct child_s {
*/
static struct child_s *child_ptr;
-static struct child_config_s {
- int maxclients, maxrequestsperchild;
- int maxspareservers, minspareservers, startservers;
+static struct child_config_s
+{
+ 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
@@ -74,47 +77,48 @@ static struct flock lock_it, unlock_it;
static int lock_fd = -1;
static void
-_child_lock_init(void)
+_child_lock_init (void)
{
- char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX";
+ char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX";
- /* Only allow u+rw bits. This may be required for some versions
- * of glibc so that mkstemp() doesn't make us vulnerable.
- */
- umask(0177);
+ /* Only allow u+rw bits. This may be required for some versions
+ * of glibc so that mkstemp() doesn't make us vulnerable.
+ */
+ umask (0177);
- 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)
+_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)
+_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 */
@@ -138,126 +142,133 @@ _child_lock_release(void)
* Set the configuration values for the various child related settings.
*/
short int
-child_configure(child_config_t type, int val)
+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);
}
/*
@@ -265,104 +276,113 @@ 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;
+ pid_t pid;
- if ((pid = fork()) > 0)
- return pid; /* parent */
+ 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);
+ /*
+ * 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;
+ child_main (ptr); /* never returns */
+ return -1;
}
/*
* Create a pool of children to handle incoming connections
*/
short int
-child_pool_create(void)
+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;
}
/*
@@ -370,88 +390,95 @@ child_pool_create(void)
* servers. It monitors this at least once a second.
*/
void
-child_main_loop(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;
+ }
+ }
}
/*
* Go through all the non-empty children and cancel them.
*/
void
-child_kill_children(void)
+child_kill_children (void)
{
- unsigned int i;
+ unsigned int i;
- for (i = 0; i != child_config.maxclients; i++) {
- if (child_ptr[i].status != T_EMPTY)
- kill(child_ptr[i].tid, SIGTERM);
- }
+ 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)
+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)
+child_close_sock (void)
{
- close(listenfd);
+ close (listenfd);
}