Ejemplo n.º 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);
}
Ejemplo n.º 2
0
/*
 * Keep the proper number of servers running. This is the birth of the
 * servers. It monitors this at least once a second.
 */
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) {
                        /*
                         * Ignore the return value of reload_config for now.
                         * This should actually be handled somehow...
                         */
                        reload_config ();

#ifdef FILTER_ENABLE
                        filter_reload ();
#endif /* FILTER_ENABLE */

                        /* propagate filter reload to all children */
                        child_kill_children (SIGHUP);

                        received_sighup = FALSE;
                }
        }
}
Ejemplo n.º 3
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);
}