the log.
Fixed CtdlThreadName(char *name) now renames thread to name if name is
set and always returns old name caller frees old name.
Added a couple of macros to change the thread names in some places for
debugging.
]
)
+dnl disable thread table reporting
+AC_ARG_WITH(threadlog,
+ [ --with-threadlog enable logging of thread table],
+ [ if test "x$withval" != "xno" ; then
+ AC_DEFINE(WITH_THREADLOG, [], [Define if you want logging of the thread tables.])
+ fi
+ ]
+)
+
if test "$ac_cv_func_gethostbyname" = no; then
AC_CHECK_LIB(nsl, gethostbyname)
}
end_critical_section(S_SESSION_TABLE);
if (killed > 0)
- lprintf(CTDL_INFO, "Terminated %d idle sessions\n", killed);
+ CtdlLogPrintf(CTDL_INFO, "Terminated %d idle sessions\n", killed);
}
void check_sched_shutdown(void) {
if ((ScheduledShutdown == 1) && (ContextList == NULL)) {
- lprintf(CTDL_NOTICE, "Scheduled shutdown initiating.\n");
+ CtdlLogPrintf(CTDL_NOTICE, "Scheduled shutdown initiating.\n");
CtdlThreadStopAll();
}
}
int new_refcounts[MAXFLOORS];
- lprintf(CTDL_DEBUG, "Checking floor reference counts\n");
+ CtdlLogPrintf(CTDL_DEBUG, "Checking floor reference counts\n");
for (a=0; a<MAXFLOORS; ++a) {
new_refcounts[a] = 0;
}
flbuf.f_flags = flbuf.f_flags & ~QR_INUSE;
}
lputfloor(&flbuf, a);
- lprintf(CTDL_DEBUG, "Floor %d: %d rooms\n", a, new_refcounts[a]);
+ CtdlLogPrintf(CTDL_DEBUG, "Floor %d: %d rooms\n", a, new_refcounts[a]);
}
}
int do_perminute_housekeeping_now = 0;
time_t now;
+ CtdlThreadPushName("do_housekeeping");
+
/*
* We do it this way instead of wrapping the whole loop in an
* S_HOUSEKEEPING critical section because it eliminates the need to
end_critical_section(S_HOUSEKEEPING);
if (do_housekeeping_now == 0) {
+ CtdlThreadPopName();
return;
}
* All done.
*/
housekeeping_in_progress = 0;
+ CtdlThreadPopName();
}
int CtdlThreadGetCount(void);
void CtdlThreadGC(void);
void CtdlThreadStopAll(void);
+#ifdef WITH_THREADLOG
+#define CtdlThreadPushName(NAME) \
+ char *_push_name; \
+ _push_name = CtdlThreadName(CtdlThreadSelf(), NAME)
+
+#define CtdlThreadPopName() \
+ free (CtdlThreadName(CtdlThreadSelf(), _push_name))
+#else
+#define CtdlThreadPushName(NAME)
+#define CtdlThreadPopName()
+#endif
#endif /* CTDL_MODULE_H */
#include "serv_vcard.h" /* Needed for vcard_getuser and extract_inet_email_addrs */
#include "journaling.h"
+#include "ctdl_module.h"
+
struct jnlq *jnlq = NULL; /* journal queue */
/*
void JournalRunQueue(void) {
struct jnlq *jptr = NULL;
+ CtdlThreadPushName("JournalRunQueue");
while (jnlq != NULL) {
begin_critical_section(S_JOURNAL_QUEUE);
if (jnlq != NULL) {
end_critical_section(S_JOURNAL_QUEUE);
JournalRunQueueMsg(jptr);
}
+ CtdlThreadPopName();
}
{
struct SessionFunctionHook *fcn = NULL;
+ CtdlThreadPushName("PerformSessionHooks");
+
for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
if (fcn->eventtype == EventType) {
(*fcn->h_function_pointer) ();
}
}
+ CtdlThreadPopName();
+
}
void PerformUserHooks(struct ctdluser *usbuf, int EventType)
{
struct UserFunctionHook *fcn = NULL;
+ CtdlThreadPushName("PerformUserHooks");
+
for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
if (fcn->eventtype == EventType) {
(*fcn->h_function_pointer) (usbuf);
}
}
+ CtdlThreadPopName();
}
int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
struct MessageFunctionHook *fcn = NULL;
int total_retval = 0;
+ CtdlThreadPushName("PerformMessageHooks");
+
/* Other code may elect to protect this message from server-side
* handlers; if this is the case, don't do anything.
lprintf(CTDL_DEBUG, "** Event type is %d, flags are %d\n",
*/
if (msg->cm_flags & CM_SKIP_HOOKS) {
lprintf(CTDL_DEBUG, "Skipping hooks\n");
+ CtdlThreadPopName();
return(0);
}
* this is an EVT_BEFORESAVE event, a nonzero return code will cause
* the save operation to abort.
*/
+ CtdlThreadPopName();
return total_retval;
}
struct RoomFunctionHook *fcn;
int total_retval = 0;
+ CtdlThreadPushName("PerformRoomHooks");
+
lprintf(CTDL_DEBUG, "Performing room hooks for <%s>\n", target_room->QRname);
for (fcn = RoomHookTable; fcn != NULL; fcn = fcn->next) {
/* Return the sum of the return codes from the hook functions.
*/
+ CtdlThreadPopName();
return total_retval;
}
struct NetprocFunctionHook *fcn;
int total_retval = 0;
+ CtdlThreadPushName("PerformNetprocHooks");
+
for (fcn = NetprocHookTable; fcn != NULL; fcn = fcn->next) {
total_retval = total_retval +
(*fcn->h_function_pointer) (msg, target_room);
/* Return the sum of the return codes from the hook functions.
* A nonzero return code will cause the message to *not* be imported.
*/
+ CtdlThreadPopName();
return total_retval;
}
{
struct DeleteFunctionHook *fcn;
+ CtdlThreadPushName("PerformDeleteHooks");
+
for (fcn = DeleteHookTable; fcn != NULL; fcn = fcn->next) {
(*fcn->h_function_pointer) (room, msgnum);
}
+ CtdlThreadPopName();
}
int total_sent = 0;
int p;
+ CtdlThreadPushName("PerformXmsgHooks");
+
for (p=0; p<MAX_XMSG_PRI; ++p) {
for (fcn = XmsgHookTable; fcn != NULL; fcn = fcn->next) {
if (fcn->order == p) {
*/
if (total_sent) break;
}
+ CtdlThreadPopName();
return total_sent;
}
return NULL;
}
begin_critical_section(S_THREAD_LIST);
+ old_name = this_thread->name;
if (name)
- {
- old_name = this_thread->name;
this_thread->name = strdup (name);
- free(old_name);
- }
- old_name = strdup(this_thread->name);
+ else
+ old_name = strdup(old_name);
end_critical_section (S_THREAD_LIST);
return (old_name);
}
worker_avg += that_thread->load_avg;
workers++;
}
+#ifdef WITH_THREADLOG
CtdlLogPrintf(CTDL_DEBUG, "CtdlThread, \"%s\" (%ld) \"%s\" %f %f %f %f.\n",
that_thread->name,
that_thread->tid,
that_thread->avg_running,
that_thread->avg_blocked,
that_thread->load_avg);
-
+#endif
pthread_mutex_unlock(&that_thread->ThreadMutex);
that_thread = that_thread->next;
}
CtdlThreadLoadAvg = load_avg/num_threads;
CtdlThreadWorkerAvg = worker_avg/workers;
+#ifdef WITH_THREADLOG
CtdlLogPrintf(CTDL_INFO, "System load average %f, workers averag %f\n", CtdlThreadLoadAvg, CtdlThreadWorkerAvg);
+#endif
end_critical_section(S_THREAD_LIST);
}
if(num_threads == 1)
CtdlThreadList->state = CTDL_THREAD_EXITED;
+#ifdef WITH_THREADLOG
CtdlLogPrintf(CTDL_DEBUG, "Thread system running garbage collection.\n");
+#endif
/*
* Woke up to do garbage collection
*/
void dead_session_purge(int force) {
struct CitContext *ptr, *ptr2; /* general-purpose utility pointer */
struct CitContext *rem = NULL; /* list of sessions to be destroyed */
-
+
+ CtdlThreadPushName("dead_session_purge");
+
if (force == 0) {
if ( (time(NULL) - last_purge) < 5 ) {
+ CtdlThreadPopName();
return; /* Too soon, go away */
}
}
}
end_critical_section(S_THREAD_LIST);
// FIXME: reduce the number of worker threads too
+
+ CtdlThreadPopName();
+
}