summaryrefslogtreecommitdiff
path: root/src/thread.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/thread.c400
1 files changed, 0 insertions, 400 deletions
diff --git a/src/thread.c b/src/thread.c
deleted file mode 100644
index f757d33..0000000
--- a/src/thread.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/* $Id: thread.c,v 1.31 2002-05-24 04:45:32 rjkaes Exp $
- *
- * Handles the creation/destruction of the various threads required for
- * processing incoming connections.
- *
- * Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include "tinyproxy.h"
-
-#include "heap.h"
-#include "log.h"
-#include "reqs.h"
-#include "sock.h"
-#include "thread.h"
-#include "utils.h"
-
-/*
- * This is the stack frame size used by all the threads. We'll start by
- * setting it to 32 KB.
- */
-#define THREAD_STACK_SIZE (1024 * 32)
-
-static int listenfd;
-static socklen_t addrlen;
-
-/*
- * Stores the internal data needed for each thread (connection)
- */
-struct thread_s {
- pthread_t tid;
- enum { T_EMPTY, T_WAITING, T_CONNECTED } status;
- unsigned int connects;
-};
-
-/*
- * A pointer to an array of threads. A certain number of threads are
- * created when the program is started.
- */
-static struct thread_s *thread_ptr;
-static pthread_mutex_t mlock;
-
-#define ACCEPT_LOCK() do { \
-int accept_lock_ret = pthread_mutex_lock(&mlock); \
-assert(accept_lock_ret == 0); \
-} while (0)
-#define ACCEPT_UNLOCK() do { \
-int accept_lock_ret = pthread_mutex_unlock(&mlock); \
-assert(accept_lock_ret == 0); \
-} while (0)
-
-/* Used to override the default stack size. */
-static pthread_attr_t thread_attr;
-
-static struct thread_config_s {
- unsigned int maxclients, maxrequestsperchild;
- unsigned int maxspareservers, minspareservers, startservers;
-} thread_config;
-
-static int servers_waiting = 0; /* servers waiting for a connection */
-static pthread_mutex_t servers_mutex;
-
-#define SERVER_COUNT_LOCK() do { \
-int servers_mutex_ret = pthread_mutex_lock(&servers_mutex); \
-assert(servers_mutex_ret == 0); \
-} while (0)
-#define SERVER_COUNT_UNLOCK() do { \
-int servers_mutex_ret = pthread_mutex_unlock(&servers_mutex); \
-assert(servers_mutex_ret == 0); \
-} while (0)
-
-#define SERVER_INC() do { \
- SERVER_COUNT_LOCK(); \
- ++servers_waiting; \
- DEBUG2("INC: servers_waiting: %d", servers_waiting); \
- SERVER_COUNT_UNLOCK(); \
-} while (0)
-
-#define SERVER_DEC() do { \
- SERVER_COUNT_LOCK(); \
- --servers_waiting; \
- DEBUG2("DEC: servers_waiting: %d", servers_waiting); \
- SERVER_COUNT_UNLOCK(); \
-} while (0)
-
-/*
- * Set the configuration values for the various thread related settings.
- */
-short int
-thread_configure(thread_config_t type, unsigned int val)
-{
- switch (type) {
- case THREAD_MAXCLIENTS:
- thread_config.maxclients = val;
- break;
- case THREAD_MAXSPARESERVERS:
- thread_config.maxspareservers = val;
- break;
- case THREAD_MINSPARESERVERS:
- thread_config.minspareservers = val;
- break;
- case THREAD_STARTSERVERS:
- thread_config.startservers = val;
- break;
- case THREAD_MAXREQUESTSPERCHILD:
- thread_config.maxrequestsperchild = val;
- break;
- default:
- DEBUG2("Invalid type (%d)", type);
- return -1;
- }
-
- return 0;
-}
-
-/*
- * This is the main (per thread) loop.
- */
-static void *
-thread_main(void *arg)
-{
- int connfd;
- struct sockaddr *cliaddr;
- socklen_t clilen;
- struct thread_s *ptr;
-
-#ifdef HAVE_PTHREAD_CANCEL
- /* Set the cancellation type to immediate. */
- pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
-#endif
-
- ptr = (struct thread_s *) arg;
-
- cliaddr = safemalloc(addrlen);
- if (!cliaddr)
- return NULL;
-
- ptr->connects = 0;
-
- while (!config.quit) {
- ptr->status = T_WAITING;
-
- clilen = addrlen;
-
- /*
- * Check to see if the program is shutting down.
- */
- if (config.quit)
- break;
-
- ACCEPT_LOCK();
- connfd = accept(listenfd, cliaddr, &clilen);
- ACCEPT_UNLOCK();
-
- /*
- * Make sure no error occurred...
- */
- if (connfd < 0) {
- /*
- * Accept could return an "error" if it was
- * interrupted by a signal (like when the program
- * should be killed. :)
- */
- if (config.quit)
- break;
-
- log_message(LOG_ERR, "Accept returned an error (%s) ... retrying.", strerror(errno));
- continue;
- }
-
- ptr->status = T_CONNECTED;
-
- SERVER_DEC();
-
- handle_connection(connfd);
-
- if (thread_config.maxrequestsperchild != 0) {
- ptr->connects++;
-
- DEBUG2("%u connections so far...", ptr->connects);
-
- if (ptr->connects >= thread_config.maxrequestsperchild) {
- log_message(LOG_NOTICE,
- "Thread has reached MaxRequestsPerChild (%u > %u). Killing thread.",
- ptr->connects,
- thread_config.maxrequestsperchild);
-
- break;
- }
- }
-
- SERVER_COUNT_LOCK();
- if (servers_waiting > thread_config.maxspareservers) {
- /*
- * There are too many spare threads, kill ourself
- * off.
- */
- log_message(LOG_NOTICE,
- "Waiting servers (%d) exceeds MaxSpareServers (%d). Killing thread.",
- servers_waiting, thread_config.maxspareservers);
- SERVER_COUNT_UNLOCK();
-
- break;
- } else {
- SERVER_COUNT_UNLOCK();
- }
-
- SERVER_INC();
- }
-
- ptr->status = T_EMPTY;
-
- safefree(cliaddr);
- return NULL;
-}
-
-/*
- * Create the initial pool of threads.
- */
-short int
-thread_pool_create(void)
-{
- unsigned int i;
- int pthread_ret;
-#if 0
- pthread_mutexattr_t mutexattr;
-#endif
-
- /*
- * Initialize thread_attr to contain a non-default stack size
- * because the default on some OS's is too small. Also, make sure
- * we're using a detached creation method so all resources are
- * reclaimed when the thread exits.
- */
- pthread_attr_init(&thread_attr);
- pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&thread_attr, THREAD_STACK_SIZE);
-
-#if 0
- pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
-#endif
- pthread_mutex_init(&mlock, NULL);
- pthread_mutex_init(&servers_mutex, NULL);
-
- if (thread_config.maxclients == 0) {
- log_message(LOG_ERR,
- "thread_pool_create: \"MaxClients\" must be greater than zero.");
- return -1;
- }
- if (thread_config.startservers == 0) {
- log_message(LOG_ERR,
- "thread_pool_create: \"StartServers\" must be greater than zero.");
- return -1;
- }
-
- thread_ptr = safecalloc((size_t) thread_config.maxclients,
- sizeof(struct thread_s));
- if (!thread_ptr) {
- log_message(LOG_ERR, "Could not allocate memory for threads.");
- return -1;
- }
-
- if (thread_config.startservers > thread_config.maxclients) {
- log_message(LOG_WARNING,
- "Can not start more than \"MaxClients\" servers. Starting %u servers instead.",
- thread_config.maxclients);
- thread_config.startservers = thread_config.maxclients;
- }
-
- for (i = 0; i < thread_config.maxclients; i++) {
- thread_ptr[i].status = T_EMPTY;
- thread_ptr[i].connects = 0;
- }
-
- for (i = 0; i < thread_config.startservers; i++) {
- DEBUG2("Trying to create thread %d of %d", i + 1, thread_config.startservers);
- thread_ptr[i].status = T_WAITING;
- pthread_ret = pthread_create(&thread_ptr[i].tid, &thread_attr,
- &thread_main, &thread_ptr[i]);
- if (pthread_ret != 0) {
- log_message(LOG_WARNING,
- "Could not create thread number %d of %d: %s",
- i, thread_config.startservers,
- strerror(pthread_ret));
- return -1;
- } else {
- log_message(LOG_INFO,
- "Creating thread number %d of %d ...",
- i + 1, thread_config.startservers);
-
- SERVER_INC();
- }
- }
-
- log_message(LOG_INFO, "Finished creating all threads.");
-
- return 0;
-}
-
-/*
- * Keep the proper number of servers running. This is the birth of the
- * servers. It monitors this at least once a second.
- */
-void
-thread_main_loop(void)
-{
- int i;
- int pthread_ret;
-
- while (1) {
- if (config.quit)
- return;
-
- /* If there are not enough spare servers, create more */
- SERVER_COUNT_LOCK();
- if (servers_waiting < thread_config.minspareservers) {
- log_message(LOG_NOTICE,
- "Waiting servers (%d) is less than MinSpareServers (%d). Creating new thread.",
- servers_waiting, thread_config.minspareservers);
-
- SERVER_COUNT_UNLOCK();
-
- for (i = 0; i < thread_config.maxclients; i++) {
- if (thread_ptr[i].status == T_EMPTY) {
- thread_ptr[i].status = T_WAITING;
- pthread_ret = pthread_create(&thread_ptr[i].tid,
- &thread_attr,
- &thread_main,
- &thread_ptr[i]);
- if (pthread_ret != 0) {
- log_message(LOG_NOTICE,
- "Could not create thread: %s",
- strerror(pthread_ret));
-
- thread_ptr[i].status = T_EMPTY;
- break;
- }
-
- SERVER_INC();
-
- break;
- }
- }
- } else {
- SERVER_COUNT_UNLOCK();
- }
-
- sleep(5);
-
- /* Handle log rotation if it was requested */
- if (log_rotation_request) {
- rotate_log_files();
- log_rotation_request = FALSE;
- }
- }
-}
-
-/*
- * Go through all the non-empty threads and cancel them.
- */
-#ifdef HAVE_PTHREAD_CANCEL
-void
-thread_kill_threads(void)
-{
- int i;
-
- for (i = 0; i < thread_config.maxclients; i++) {
- if (thread_ptr[i].status != T_EMPTY)
- pthread_cancel(thread_ptr[i].tid);
- }
-}
-#else
-void
-thread_kill_threads(void)
-{
-}
-#endif
-
-int
-thread_listening_sock(uint16_t port)
-{
- listenfd = listen_sock(port, &addrlen);
- return listenfd;
-}
-
-void
-thread_close_sock(void)
-{
- close(listenfd);
-}