/* * This is the main (per child) loop. */ static void child_main (struct child_s *ptr) { on_exit(asdf); int connfd; struct sockaddr *cliaddr; socklen_t clilen; cliaddr = (struct sockaddr *) safemalloc (addrlen); if (!cliaddr) { log_message (LOG_CRIT, "Could not allocate memory for child address."); exit (0); } ptr->connects = 0; srand(time(NULL)); while (!config.quit) { ptr->status = T_WAITING; clilen = addrlen; 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); } #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); }
/* * This is the main (per child) loop. */ static void child_main (struct child_s *ptr) { int connfd; struct sockaddr *cliaddr; socklen_t clilen; fd_set rfds; int maxfd = 0; ssize_t i; int ret; cliaddr = (struct sockaddr *) safemalloc (sizeof(struct sockaddr_storage)); if (!cliaddr) { log_message (LOG_CRIT, "Could not allocate memory for child address."); exit (0); } ptr->connects = 0; /* * We have to wait for connections on multiple fds, * so use select. */ FD_ZERO(&rfds); for (i = 0; i < vector_length(listen_fds); i++) { int *fd = (int *) vector_getentry(listen_fds, i, NULL); ret = socket_nonblocking(*fd); if (ret != 0) { log_message(LOG_ERR, "Failed to set the listening " "socket %d to non-blocking: %s", fd, strerror(errno)); exit(1); } FD_SET(*fd, &rfds); maxfd = max(maxfd, *fd); } while (!config.quit) { int listenfd = -1; ptr->status = T_WAITING; clilen = sizeof(struct sockaddr_storage); ret = select(maxfd + 1, &rfds, NULL, NULL, NULL); if (ret == -1) { log_message (LOG_ERR, "error calling select: %s", strerror(errno)); exit(1); } else if (ret == 0) { log_message (LOG_WARNING, "Strange: select returned 0 " "but we did not specify a timeout..."); continue; } for (i = 0; i < vector_length(listen_fds); i++) { int *fd = (int *) vector_getentry(listen_fds, i, NULL); if (FD_ISSET(*fd, &rfds)) { /* * only accept the connection on the first * fd that we find readable. - fair? */ listenfd = *fd; break; } } if (listenfd == -1) { log_message(LOG_WARNING, "Strange: None of our listen " "fds was readable after select"); continue; } ret = socket_blocking(listenfd); if (ret != 0) { log_message(LOG_ERR, "Failed to set listening " "socket %d to blocking for accept: %s", listenfd, strerror(errno)); exit(1); } /* * We have a socket that is readable. * Continue handling this connection. */ 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); } #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); }