Example #1
0
/*
 * 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);
}
Example #2
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);
}