in order to prepare for the forthcoming simplification of the server thread architecture
-dnl Checks for the Boehm-Demers-Weiser garbage collection library.
-if test "x$with_gc" != xno ; then
- AC_CHECK_HEADERS(gc/gc_local_alloc.h,
- [AC_CHECK_LIB(gc, GC_init,
- [ok_gc=yes],,
- )])
-fi
-
-if test "x$ok_gc" = xyes ; then
- SERVER_LIBS="-lgc $SERVER_LIBS"
- AC_DEFINE(HAVE_GC, [], [define this if you have Boehm-Demers-Weiser available])
-fi
-
-
-
-
dnl Checks for the libdspam mail spam scanning library.
dnl if test "x$with_libdspam" != xno ; then
void terminate_stuck_sessions(void)
{
- return;
+ abort();
+
/* FIXME this function has been disabled because it is somehow being
* called at times other than server shutdown, which is throwing all
* the users off. EPIC FAIL!!!
int do_housekeeping_now = 0;
int do_perminute_housekeeping_now = 0;
time_t now;
- const char *old_name;
/*
* We do it this way instead of wrapping the whole loop in an
*/
/* First, do the "as often as needed" stuff... */
- old_name = CtdlThreadName("House Keeping - Journal");
JournalRunQueue();
-
- CtdlThreadName("House Keeping - EVT_HOUSE");
- PerformSessionHooks(EVT_HOUSE); /* perform as needed housekeeping */
+ PerformSessionHooks(EVT_HOUSE);
/* Then, do the "once per minute" stuff... */
if (do_perminute_housekeeping_now) {
cdb_check_handles(); /* suggested by Justin Case */
- CtdlThreadName("House Keeping - EVT_TIMER");
PerformSessionHooks(EVT_TIMER); /* Run any timer hooks */
}
* All done.
*/
housekeeping_in_progress = 0;
- CtdlThreadName(old_name);
}
/*
* checkpointing module for the database
*
- * Copyright (c) 1987-2009 by the citadel.org team
+ * Copyright (c) 1987-2011 by the citadel.org team
*
- * 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 3 of the License, or
- * (at your option) any later version.
+ * This program is open source 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 3 of the License, 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.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sysdep.h"
#include "ctdl_module.h"
#include "context.h"
-/*
- * Main loop for the checkpoint thread.
- */
-void *checkpoint_thread(void *arg) {
- struct CitContext checkpointCC;
-
-
- CtdlFillSystemContext(&checkpointCC, "checkpoint");
- citthread_setspecific(MyConKey, (void *)&checkpointCC );
-
- syslog(LOG_DEBUG, "checkpoint_thread() initializing\n");
- while (!CtdlThreadCheckStop()) {
- cdb_checkpoint();
- CtdlThreadSleep(60);
- }
-
- syslog(LOG_DEBUG, "checkpoint_thread() exiting\n");
- CtdlClearSystemContext();
- return NULL;
-}
CTDL_MODULE_INIT(checkpoint) {
if (threading)
{
- CtdlThreadCreate ("checkpoint", CTDLTHREAD_BIGSTACK, checkpoint_thread, NULL);
+ CtdlRegisterSessionHook(cdb_checkpoint, EVT_TIMER);
}
/* return our Subversion id for the Log */
return "checkpoint";
*
* You might also see this module affectionately referred to as the DAP (the Dreaded Auto-Purger).
*
- * Copyright (c) 1988-2009 by citadel.org (Art Cancro, Wilifried Goesgens, and others)
+ * Copyright (c) 1988-2011 by citadel.org (Art Cancro, Wilifried Goesgens, and others)
*
- * 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 3 of the License, or
- * (at your option) any later version.
+ * This program is open source 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 3 of the License, 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.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* A brief technical discussion:
time_t xtime, now;
struct CtdlMessage *msg = NULL;
int a;
- struct cdbdata *cdbfr;
+ struct cdbdata *cdbfr;
long *msglist = NULL;
int num_msgs = 0;
FILE *purgelist;
if (!strcasecmp(qrbuf->QRname, SYSCONFIGROOM)) return;
/* Ok, we got this far ... now let's see what's in the room */
- cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf->QRnumber, sizeof(long));
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf->QRnumber, sizeof(long));
- if (cdbfr != NULL) {
- msglist = malloc(cdbfr->len);
- memcpy(msglist, cdbfr->ptr, cdbfr->len);
- num_msgs = cdbfr->len / sizeof(long);
- cdb_free(cdbfr);
+ if (cdbfr != NULL) {
+ msglist = malloc(cdbfr->len);
+ memcpy(msglist, cdbfr->ptr, cdbfr->len);
+ num_msgs = cdbfr->len / sizeof(long);
+ cdb_free(cdbfr);
}
/* Nothing to do if there aren't any messages */
* this will release this file from the serv_network.h
* Maybe it could be a macro that extracts and casts the reult
*/
- memcpy(&ut, cdbut->ptr,
- ((cdbut->len > sizeof(struct UseTable)) ?
- sizeof(struct UseTable) : cdbut->len));
- cdb_free(cdbut);
+ memcpy(&ut, cdbut->ptr,
+ ((cdbut->len > sizeof(struct UseTable)) ?
+ sizeof(struct UseTable) : cdbut->len));
+ cdb_free(cdbut);
if ( (time(NULL) - ut.ut_timestamp) > USETABLE_RETAIN ) {
uptr = (struct UPurgeList *) malloc(sizeof(struct UPurgeList));
++purged;
}
- cdb_free(cdbei);
+ cdb_free(cdbei);
}
-void *purge_databases(void *args)
+void purge_databases(void)
{
- int retval;
- static time_t last_purge = 0;
- time_t now;
- struct tm tm;
- struct CitContext purgerCC;
-
- CtdlFillSystemContext(&purgerCC, "purger");
- citthread_setspecific(MyConKey, (void *)&purgerCC );
- syslog(LOG_DEBUG, "Auto-purger_thread() initializing\n");
-
- while (!CtdlThreadCheckStop()) {
- /* Do the auto-purge if the current hour equals the purge hour,
- * but not if the operation has already been performed in the
- * last twelve hours. This is usually enough granularity.
- */
- now = time(NULL);
- localtime_r(&now, &tm);
- if (
- ((tm.tm_hour != config.c_purge_hour) || ((now - last_purge) < 43200))
- && (force_purge_now == 0)
- ) {
- CtdlThreadSleep(60);
- continue;
- }
-
-
- syslog(LOG_INFO, "Auto-purger: starting.\n");
-
- if (!CtdlThreadCheckStop())
- {
- retval = PurgeUsers();
- syslog(LOG_NOTICE, "Purged %d users.\n", retval);
- }
-
- if (!CtdlThreadCheckStop())
- {
- PurgeMessages();
- syslog(LOG_NOTICE, "Expired %d messages.\n", messages_purged);
- }
-
- if (!CtdlThreadCheckStop())
- {
- retval = PurgeRooms();
- syslog(LOG_NOTICE, "Expired %d rooms.\n", retval);
- }
-
- if (!CtdlThreadCheckStop())
- {
- retval = PurgeVisits();
- syslog(LOG_NOTICE, "Purged %d visits.\n", retval);
- }
-
- if (!CtdlThreadCheckStop())
- {
- retval = PurgeUseTable();
- syslog(LOG_NOTICE, "Purged %d entries from the use table.\n", retval);
- }
-
- if (!CtdlThreadCheckStop())
- {
- retval = PurgeEuidIndexTable();
- syslog(LOG_NOTICE, "Purged %d entries from the EUID index.\n", retval);
- }
-
- if (!CtdlThreadCheckStop())
- {
- retval = PurgeStaleOpenIDassociations();
- syslog(LOG_NOTICE, "Purged %d stale OpenID associations.\n", retval);
- }
-
- if (!CtdlThreadCheckStop())
- {
- retval = TDAP_ProcessAdjRefCountQueue();
- syslog(LOG_NOTICE, "Processed %d message reference count adjustments.\n", retval);
- }
-
- if (!CtdlThreadCheckStop())
- {
- syslog(LOG_INFO, "Auto-purger: finished.\n");
- last_purge = now; /* So we don't do it again soon */
- force_purge_now = 0;
- }
- else
- syslog(LOG_INFO, "Auto-purger: STOPPED.\n");
-
- }
- CtdlClearSystemContext();
- return NULL;
-}
-/*****************************************************************************/
-
-
-/* The FSCK command has been removed because people were misusing it */
-
-#if 0
-
-void do_fsck_msg(long msgnum, void *userdata) {
- struct ctdlroomref *ptr;
-
- ptr = (struct ctdlroomref *)malloc(sizeof(struct ctdlroomref));
- ptr->next = rr;
- ptr->msgnum = msgnum;
- rr = ptr;
-}
-
-void do_fsck_room(struct ctdlroom *qrbuf, void *data)
-{
- CtdlGetRoom(&CC->room, qrbuf->QRname);
- CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, do_fsck_msg, NULL);
-}
-
-/*
- * Check message reference counts
- */
-void cmd_fsck(char *argbuf) {
- long msgnum;
- struct cdbdata *cdbmsg;
- struct MetaData smi;
- struct ctdlroomref *ptr;
- int realcount;
-
- if (CtdlAccessCheck(ac_aide)) return;
+ int retval;
+ static time_t last_purge = 0;
+ time_t now;
+ struct tm tm;
- /* Lame way of checking whether anyone else is doing this now */
- if (rr != NULL) {
- cprintf("%d Another FSCK is already running.\n", ERROR + RESOURCE_BUSY);
- return;
+ /* Do the auto-purge if the current hour equals the purge hour,
+ * but not if the operation has already been performed in the
+ * last twelve hours. This is usually enough granularity.
+ */
+ now = time(NULL);
+ localtime_r(&now, &tm);
+ if (
+ ((tm.tm_hour != config.c_purge_hour) || ((now - last_purge) < 43200))
+ && (force_purge_now == 0)
+ ) {
+ return;
}
- cprintf("%d Checking message reference counts\n", LISTING_FOLLOWS);
+ syslog(LOG_INFO, "Auto-purger: starting.\n");
- cprintf("\nThis could take a while. Please be patient!\n\n");
- cprintf("Gathering pointers...\n");
- CtdlForEachRoom(do_fsck_room, NULL);
-
- get_control();
- cprintf("Checking message base...\n");
- for (msgnum = 0L; msgnum <= CitControl.MMhighest; ++msgnum) {
-
- cdbmsg = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long));
- if (cdbmsg != NULL) {
- cdb_free(cdbmsg);
- cprintf("Message %7ld ", msgnum);
+ if (!CtdlThreadCheckStop())
+ {
+ retval = PurgeUsers();
+ syslog(LOG_NOTICE, "Purged %d users.\n", retval);
+ }
+
+ if (!CtdlThreadCheckStop())
+ {
+ PurgeMessages();
+ syslog(LOG_NOTICE, "Expired %d messages.\n", messages_purged);
+ }
- GetMetaData(&smi, msgnum);
- cprintf("refcount=%-2d ", smi.meta_refcount);
+ if (!CtdlThreadCheckStop())
+ {
+ retval = PurgeRooms();
+ syslog(LOG_NOTICE, "Expired %d rooms.\n", retval);
+ }
- realcount = 0;
- for (ptr = rr; ptr != NULL; ptr = ptr->next) {
- if (ptr->msgnum == msgnum) ++realcount;
- }
- cprintf("realcount=%-2d\n", realcount);
+ if (!CtdlThreadCheckStop())
+ {
+ retval = PurgeVisits();
+ syslog(LOG_NOTICE, "Purged %d visits.\n", retval);
+ }
- if ( (smi.meta_refcount != realcount)
- || (realcount == 0) ) {
- AdjRefCount(msgnum, (smi.meta_refcount - realcount));
- }
+ if (!CtdlThreadCheckStop())
+ {
+ retval = PurgeUseTable();
+ syslog(LOG_NOTICE, "Purged %d entries from the use table.\n", retval);
+ }
- }
+ if (!CtdlThreadCheckStop())
+ {
+ retval = PurgeEuidIndexTable();
+ syslog(LOG_NOTICE, "Purged %d entries from the EUID index.\n", retval);
+ }
+ if (!CtdlThreadCheckStop())
+ {
+ retval = PurgeStaleOpenIDassociations();
+ syslog(LOG_NOTICE, "Purged %d stale OpenID associations.\n", retval);
}
- cprintf("Freeing memory...\n");
- while (rr != NULL) {
- ptr = rr->next;
- free(rr);
- rr = ptr;
+ if (!CtdlThreadCheckStop())
+ {
+ retval = TDAP_ProcessAdjRefCountQueue();
+ syslog(LOG_NOTICE, "Processed %d message reference count adjustments.\n", retval);
}
- cprintf("Done!\n");
- cprintf("000\n");
+ if (!CtdlThreadCheckStop())
+ {
+ syslog(LOG_INFO, "Auto-purger: finished.\n");
+ last_purge = now; /* So we don't do it again soon */
+ force_purge_now = 0;
+ }
+ else {
+ syslog(LOG_INFO, "Auto-purger: STOPPED.\n");
+ }
+ CtdlClearSystemContext();
}
-#endif /* end of commented-out fsck cmd */
/*
* Manually initiate a run of The Dreaded Auto-Purger (tm)
}
-/*****************************************************************************/
CTDL_MODULE_INIT(expire)
{
if (!threading)
{
- /* CtdlRegisterProtoHook(cmd_fsck, "FSCK", "Check message ref counts"); */
CtdlRegisterProtoHook(cmd_tdap, "TDAP", "Manually initiate auto-purger");
-
CtdlRegisterProtoHook(cmd_gpex, "GPEX", "Get expire policy");
CtdlRegisterProtoHook(cmd_spex, "SPEX", "Set expire policy");
+ CtdlRegisterSessionHook(purge_databases, EVT_TIMER);
}
- else
- CtdlThreadCreate("Auto Purger", CTDLTHREAD_BIGSTACK, purge_databases, NULL);
+
/* return our Subversion id for the Log */
return "expire";
}
/*
* This module handles fulltext indexing of the message base.
- * Copyright (c) 2005-2009 by the citadel.org team
+ * Copyright (c) 2005-2011 by the citadel.org team
*
- * This program is free software; you can redistribute it and/or modify
+ * This program is open source 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 3 of the License, or
* (at your option) any later version.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ctdl_module.h"
-
-
long ft_newhighest = 0L;
long *ft_newmsgs = NULL;
int ft_num_msgs = 0;
int ft_num_alloc = 0;
-
int ftc_num_msgs[65536];
long *ftc_msgs[65536];
static time_t last_progress = 0L;
time_t run_time = 0L;
time_t end_time = 0L;
+ static int is_running = 0;
+ if (is_running) return; /* Concurrency check - only one can run */
+ is_running = 1;
/*
* Don't do this if the site doesn't have it enabled.
* Make sure we don't run the indexer too frequently.
* FIXME move the setting into config
*/
-/*
- * The thread sleeps for 300 seconds so we don't need this here any more
if ( (time(NULL) - last_index) < 300L) {
return;
}
-*/
/*
* Check to see whether the fulltext index is up to date; if there
}
end_time = time(NULL);
- if (CtdlThreadCheckStop())
+ if (CtdlThreadCheckStop()) {
+ is_running = 0;
return;
+ }
syslog(LOG_DEBUG, "do_fulltext_indexing() duration (%ld)\n", end_time - run_time);
last_index = time(NULL);
syslog(LOG_DEBUG, "do_fulltext_indexing() finished\n");
+ is_running = 0;
return;
}
-/*
- * Main loop for the indexer thread.
- */
-void *indexer_thread(void *arg) {
- struct CitContext indexerCC;
-
-
- CtdlFillSystemContext(&indexerCC, "indexer");
- citthread_setspecific(MyConKey, (void *)&indexerCC );
- syslog(LOG_DEBUG, "indexer_thread() initializing\n");
-
- while (!CtdlThreadCheckStop()) {
- do_fulltext_indexing();
- CtdlThreadSleep(300);
- }
-
- syslog(LOG_DEBUG, "indexer_thread() exiting\n");
- CtdlClearSystemContext();
- return NULL;
-}
-
/*
CtdlRegisterDeleteHook(ft_delete_remove);
CtdlRegisterSearchFuncHook(ft_search, "fulltext");
CtdlRegisterCleanupHook(noise_word_cleanup);
- }
- else
- {
- CtdlThreadCreate("Indexer", CTDLTHREAD_BIGSTACK, indexer_thread, NULL);
+ CtdlRegisterSessionHook(do_fulltext_indexing, EVT_TIMER);
}
/* return our Subversion id for the Log */
return "fulltext";
* This module handles shared rooms, inter-Citadel mail, and outbound
* mailing list processing.
*
- * Copyright (c) 2000-2010 by the citadel.org team
+ * Copyright (c) 2000-2011 by the citadel.org team
*
- * This program is free software; you can redistribute it and/or modify
+ * This program is open source 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 3 of the License, or
* (at your option) any later version.
-/* Nonzero while we are doing network processing */
-static int doing_queue = 0;
-
/*
* When we do network processing, it's accomplished in two passes; one to
* gather a list of rooms and one to actually do them. It's ok that rplist
* Run through the rooms doing various types of network stuff.
*/
void network_do_queue(void) {
+ static int doing_queue = 0;
static time_t last_run = 0L;
struct RoomProcList *ptr;
int full_processing = 1;
return 0;
}
-void *ignet_thread(void *arg) {
- struct CitContext ignet_thread_CC;
-
- syslog(LOG_DEBUG, "ignet_thread() initializing\n");
- CtdlFillSystemContext(&ignet_thread_CC, "IGnet Queue");
- citthread_setspecific(MyConKey, (void *)&ignet_thread_CC);
-
- while (!CtdlThreadCheckStop()) {
- network_do_queue();
- CtdlThreadSleep(60);
- }
-
- CtdlClearSystemContext();
- return(NULL);
-}
-
-
-
/*
* Module entry point
CtdlRegisterProtoHook(cmd_nsyn, "NSYN", "Synchronize room to node");
CtdlRegisterRoomHook(network_room_handler);
CtdlRegisterCleanupHook(destroy_network_queue_room);
- CtdlThreadCreate("SMTP Send", CTDLTHREAD_BIGSTACK, ignet_thread, NULL);
+ CtdlRegisterSessionHook(network_do_queue, EVT_TIMER);
}
return "network";
}
* The VRFY and EXPN commands have been removed from this implementation
* because nobody uses these commands anymore, except for spammers.
*
- * Copyright (c) 1998-2009 by the citadel.org team
+ * Copyright (c) 1998-2011 by the citadel.org team
*
- * This program is free software; you can redistribute it and/or modify
+ * This program is open source 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 3 of the License, or
* (at your option) any later version.
*
* Run through the queue sending out messages.
*/
-void *smtp_queue_thread(void *arg) {
+void smtp_do_queue(void) {
+ static int is_running = 0;
int num_processed = 0;
- struct CitContext smtp_queue_CC;
- CtdlFillSystemContext(&smtp_queue_CC, "SMTP Send");
- citthread_setspecific(MyConKey, (void *)&smtp_queue_CC);
- syslog(LOG_DEBUG, "smtp_queue_thread() initializing\n");
+ if (is_running) return; /* Concurrency check - only one can run */
+ is_running = 1;
- while (!CtdlThreadCheckStop()) {
-
- syslog(LOG_INFO, "SMTP client: processing outbound queue\n");
+ syslog(LOG_INFO, "SMTP client: processing outbound queue\n");
- if (CtdlGetRoom(&CC->room, SMTP_SPOOLOUT_ROOM) != 0) {
- syslog(LOG_ERR, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
- }
- else {
- num_processed = CtdlForEachMessage(MSGS_ALL, 0L, NULL, SPOOLMIME, NULL, smtp_do_procmsg, NULL);
- }
- syslog(LOG_INFO, "SMTP client: queue run completed; %d messages processed\n", num_processed);
- CtdlThreadSleep(60);
+ if (CtdlGetRoom(&CC->room, SMTP_SPOOLOUT_ROOM) != 0) {
+ syslog(LOG_ERR, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
}
-
- CtdlClearSystemContext();
- return(NULL);
+ else {
+ num_processed = CtdlForEachMessage(MSGS_ALL, 0L, NULL, SPOOLMIME, NULL, smtp_do_procmsg, NULL);
+ }
+ syslog(LOG_INFO, "SMTP client: queue run completed; %d messages processed\n", num_processed);
+ is_running = 0;
}
if (!threading)
{
smtp_init_spoolout();
- CtdlThreadCreate("SMTP Send", CTDLTHREAD_BIGSTACK, smtp_queue_thread, NULL);
+ CtdlRegisterSessionHook(smtp_do_queue, EVT_TIMER);
CtdlRegisterProtoHook(cmd_smtp, "SMTP", "SMTP utility commands");
}
// eCrashSymbolTable symbol_table;
#endif
-#ifdef HAVE_GC
- GC_INIT();
- GC_find_leak = 1;
-#endif
-
-
/* initialise semaphores here. Patch by Matt and davew
* its called here as they are needed by syslog for thread safety
*/
running_as_daemon = 1;
}
- /* run a few stats if -s was specified */
- else if (!strncmp(argv[a], "-s", 2)) {
- statcount = atoi(&argv[a][2]);
- }
-
else if (!strncmp(argv[a], "-h", 2)) {
relh=argv[a][2]!='/';
if (!relh) safestrncpy(ctdl_home_directory, &argv[a][2],
go_threading();
-
master_cleanup(exit_signal);
return(0);
}
*/
sigemptyset(&set);
sigaddset(&set, SIGINT); // intr = shutdown
- // sigaddset(&set, SIGQUIT); // quit = force quit
sigaddset(&set, SIGHUP);
sigaddset(&set, SIGTERM);
- // sigaddset(&set, SIGSEGV); // we want core dumps
- // sigaddset(&set, SIGILL); // we want core dumps
- // sigaddset(&set, SIGBUS);
sigprocmask(SIG_UNBLOCK, &set, NULL);
signal(SIGINT, signal_cleanup); // intr = shutdown
- // signal(SIGQUIT, signal_cleanup); // quit = force quit
signal(SIGHUP, signal_cleanup);
signal(SIGTERM, signal_cleanup);
signal(SIGUSR2, signal_exit);
- // signal(SIGSEGV, signal_cleanup); // we want coredumps
- // signal(SIGILL, signal_cleanup); // we want core dumps
- // signal(SIGBUS, signal_cleanup);
/*
* Do not shut down the server on broken pipe signals, otherwise the
/*
* This loop just keeps going and going and going...
*/
-/*
- * FIXME:
- * This current implimentation of worker_thread creates a bottle neck in several situations
- * The first thing to remember is that a single thread can handle more than one connection at a time.
- * More threads mean less memory for the system to run in.
- * So for efficiency we want every thread to be doing something useful or waiting in the main loop for
- * something to happen anywhere.
- * This current implimentation requires worker threads to wait in other locations, after it has
- * been committed to a single connection which is very wasteful.
- * As an extreme case consider this:
- * A slow client connects and this slow client sends only one character each second.
- * With this current implimentation a single worker thread is dispatched to handle that connection
- * until such times as the client timeout expires, an error occurs on the socket or the client
- * completes its transmission.
- * THIS IS VERY BAD since that thread could have handled a read from many more clients in each one
- * second interval between chars.
- *
- * It is my intention to re-write this code and the associated client_getln, client_read functions
- * to allow any thread to read data on behalf of any connection (context).
- * To do this I intend to have this main loop read chars into a buffer stored in the context.
- * Once the correct criteria for a full buffer is met then we will dispatch a thread to
- * process it.
- * This worker thread loop also needs to be able to handle binary data.
- */
-
void *worker_thread(void *arg) {
int highest;
CitContext *ptr;
static int num_threads = 0; /* Current number of threads */
static int num_workers = 0; /* Current number of worker threads */
-long statcount = 0; /* are we doing a stats check? */
-static long stats_done = 0;
CtdlThreadNode *CtdlThreadList = NULL;
CtdlThreadNode *CtdlThreadSchedList = NULL;
extern void close_masters (void);
-void *simulation_worker (void*arg) {
- struct CitContext *this;
-
- this = CreateNewContext();
- CtdlThreadSleep(1);
- this->kill_me = KILLME_SIMULATION_WORKER;
- this->state = CON_IDLE;
- dead_session_purge(1);
- begin_critical_section(S_SESSION_TABLE);
- stats_done++;
- end_critical_section(S_SESSION_TABLE);
- return NULL;
-}
-
-
-void *simulation_thread (void *arg)
-{
- long stats = statcount;
-
- while(stats && !CtdlThreadCheckStop()) {
- CtdlThreadCreate("Connection simulation worker", CTDLTHREAD_BIGSTACK, simulation_worker, NULL);
- stats--;
- }
- CtdlThreadStopAll();
- return NULL;
-}
void go_threading(void)
{
ctdl_thread_internal_init();
/* Second call to module init functions now that threading is up */
- if (!statcount) {
- initialise_modules(1);
- CtdlThreadCreate("select_on_master", CTDLTHREAD_BIGSTACK, select_on_master, NULL);
- }
- else {
- syslog(LOG_EMERG, "Running connection simulation stats\n");
- gettimeofday(&start, NULL);
- CtdlThreadCreate("Connection simulation master", CTDLTHREAD_BIGSTACK, simulation_thread, NULL);
- }
-
+ initialise_modules(1);
+ CtdlThreadCreate("select_on_master", CTDLTHREAD_BIGSTACK, select_on_master, NULL);
/*
* This thread is now used for garbage collection of other threads in the thread list
/* FIXME: come up with a better way to dynamically alter the number of threads
* based on the system load
*/
- if (!statcount) {
- if ((((CtdlThreadGetWorkers() < config.c_max_workers) && (CtdlThreadGetWorkerAvg() > 60)) || CtdlThreadGetWorkers() < config.c_min_workers) && (CT->state > CTDL_THREAD_STOP_REQ))
+ if ( (((CtdlThreadGetWorkers() < config.c_max_workers)
+ && (CtdlThreadGetWorkerAvg() > 60))
+ || CtdlThreadGetWorkers() < config.c_min_workers)
+ && (CT->state > CTDL_THREAD_STOP_REQ)
+ )
{
/* Only start new threads if we are not going to overload the machine */
/* Temporarily set to 10 should be enough to make sure we don't stranglew the server
else
syslog(LOG_WARNING, "Server strangled due to machine load average too high.\n");
}
- }
CtdlThreadGC();
* If the above loop exits we must be shutting down since we obviously have no threads
*/
ctdl_thread_internal_cleanup();
-
- if (statcount) {
- gettimeofday(&now, NULL);
- timersub(&now, &start, &result);
- last_duration = (double)result.tv_sec + ((double)result.tv_usec / (double) 1000000);
- syslog(LOG_EMERG, "Simulated %ld connections in %f seconds\n", stats_done, last_duration);
- }
}