From 0c5e8a2f96dd22534c0b7189ff5e75519be03b82 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Dec 2007 11:55:35 +0000 Subject: moved core threading helpers out of syslogd.c --- threads.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 threads.c (limited to 'threads.c') diff --git a/threads.c b/threads.c new file mode 100644 index 00000000..c3aee4b8 --- /dev/null +++ b/threads.c @@ -0,0 +1,123 @@ +/* threads.c + * + * This file implements threading support helpers (and maybe the thread object) + * for rsyslog. + * + * File begun on 2007-12-14 by RGerhards + * + * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Rsyslog 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. + * + * Rsyslog 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 Rsyslog. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include "rsyslog.h" + +#include +#include +#include +#include + +#include "syslogd.h" +#include "threads.h" + +int iMainMsgQueueSize; +msgQueue *pMsgQueue = NULL; + +msgQueue *queueInit (void) +{ + msgQueue *q; + + q = (msgQueue *)malloc(sizeof(msgQueue)); + if (q == NULL) return (NULL); + if((q->pbuf = malloc(sizeof(void *) * iMainMsgQueueSize)) == NULL) { + free(q); + return NULL; + } + + q->empty = 1; + q->full = 0; + q->head = 0; + q->tail = 0; + q->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t)); + pthread_mutex_init (q->mut, NULL); + q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); + pthread_cond_init (q->notFull, NULL); + q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); + pthread_cond_init (q->notEmpty, NULL); + + return (q); +} + +void queueDelete (msgQueue *q) +{ + pthread_mutex_destroy (q->mut); + free (q->mut); + pthread_cond_destroy (q->notFull); + free (q->notFull); + pthread_cond_destroy (q->notEmpty); + free (q->notEmpty); + free(q->pbuf); + free (q); +} + + +/* In queueAdd() and queueDel() we have a potential race condition. If a message + * is dequeued and at the same time a message is enqueued and the queue is either + * full or empty, the full (or empty) indicator may be invalidly updated. HOWEVER, + * this does not cause any real problems. No queue pointers can be wrong. And even + * if one of the flags is set invalidly, that does not pose a real problem. If + * "full" is invalidly set, at mose one message might be lost, if we are already in + * a timeout situation (this is quite acceptable). And if "empty" is accidently set, + * the receiver will not continue the inner loop, but break out of the outer. So no + * harm is done at all. For this reason, I do not yet use a mutex to guard the two + * flags - there would be a notable performance hit with, IMHO, no gain in stability + * or functionality. But anyhow, now it's documented... + * rgerhards, 2007-09-20 + * NOTE: this comment does not really apply - the callers handle the mutex, so it + * *is* guarded. + */ +void queueAdd (msgQueue *q, void* in) +{ + q->pbuf[q->tail] = in; + q->tail++; + if (q->tail == iMainMsgQueueSize) + q->tail = 0; + if (q->tail == q->head) + q->full = 1; + q->empty = 0; + + return; +} + +void queueDel(msgQueue *q, void **out) +{ + *out = (void*) q->pbuf[q->head]; + + q->head++; + if (q->head == iMainMsgQueueSize) + q->head = 0; + if (q->head == q->tail) + q->empty = 1; + q->full = 0; + + return; +} + +/* + * vi:set ai: + */ -- cgit v1.2.3 From 6c0c26dc96544aa5814d00045b3d559c99fc1b2e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Dec 2007 16:51:34 +0000 Subject: on the way to a real input module interface and threading class... --- threads.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index c3aee4b8..d5168d02 100644 --- a/threads.c +++ b/threads.c @@ -27,17 +27,111 @@ #include "config.h" #include "rsyslog.h" -#include #include #include +#include +#include #include #include "syslogd.h" +#include "linkedlist.h" #include "threads.h" +/* static data */ int iMainMsgQueueSize; msgQueue *pMsgQueue = NULL; +/* linked list of currently-known threads */ +static linkedList_t llThrds; + +/* methods */ + +/* Construct a new thread object + */ +static rsRetVal thrdConstruct(thrdInfo_t **pThis) +{ + thrdInfo_t *pNew; + + if((pNew = calloc(1, sizeof(thrdInfo_t))) == NULL) + return RS_RET_OUT_OF_MEMORY; + + /* OK, we got the element, now initialize members that should + * not be zero-filled. + */ + + *pThis = pNew; + return RS_RET_OK; +} + + +/* Destructs a thread object. The object must not be linked to the + * linked list of threads. Please note that the thread should have been + * stopped before. If not, we try to do it. + */ +static rsRetVal thrdDestruct(thrdInfo_t *pThis) +{ + assert(pThis != NULL); + + if(pThis->bIsActive == 1) { + thrdTerminate(pThis); + } + free(pThis); + + return RS_RET_OK; +} + + +/* terminate a thread gracefully. It's termination sync state is taken into + * account. + */ +rsRetVal thrdTerminate(thrdInfo_t *pThis) +{ + assert(pThis != NULL); + + if(pThis->eTermTool == eTermSync_SIGNAL) { + pthread_kill(pThis->thrdID, SIGUSR2); + pthread_join(pThis->thrdID, NULL); + /* TODO: TIMEOUT! */ + } else if(pThis->eTermTool == eTermSync_NONE) { + pthread_cancel(pThis->thrdID); + } + pThis->bIsActive = 0; + + return RS_RET_OK; +} + + +/* initialize the thread-support subsystem + * must be called once at the start of the program + */ +rsRetVal thrdInit(void) +{ + DEFiRet; + + iRet = llInit(&llThrds, thrdDestruct, NULL, NULL); + + return iRet; +} + + +/* de-initialize the thread subsystem + * must be called once at the end of the program + */ +rsRetVal thrdExit(void) +{ + DEFiRet; + + iRet = llDestroy(&llThrds); + + return iRet; +} + + + +/* queue functions (may be migrated to some other file...) + */ + + msgQueue *queueInit (void) { msgQueue *q; -- cgit v1.2.3 From 3a209d530568ddfb448d3b55e506022245e394b4 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Dec 2007 17:15:35 +0000 Subject: added thread activation --- threads.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'threads.c') diff --git a/threads.c b/threads.c index d5168d02..d58a291f 100644 --- a/threads.c +++ b/threads.c @@ -101,6 +101,26 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) } +/* Start a new thread and add it to the list of currently + * executing threads. It is added at the end of the list. + * rgerhards, 2007-12-14 + */ +rsRetVal thrdCreate(void* (*thrdMain)(void*)) +{ + DEFiRet; + thrdInfo_t *pThis; + int i; + + assert(thrdMain != NULL); + + CHKiRet(thrdConstruct(&pThis)); + i = pthread_create(&pThis->thrdID, NULL, thrdMain, NULL); + +finalize_it: + return iRet; +} + + /* initialize the thread-support subsystem * must be called once at the start of the program */ -- cgit v1.2.3 From 8d186b303650c1d942543e28fdf8cf28a451f438 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Dec 2007 17:34:54 +0000 Subject: first rough version of input module thread termination --- threads.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'threads.c') diff --git a/threads.c b/threads.c index d58a291f..96911403 100644 --- a/threads.c +++ b/threads.c @@ -71,6 +71,7 @@ static rsRetVal thrdConstruct(thrdInfo_t **pThis) static rsRetVal thrdDestruct(thrdInfo_t *pThis) { assert(pThis != NULL); +dbgprintf("thrdDestruct, pThis: %lx\n", pThis); if(pThis->bIsActive == 1) { thrdTerminate(pThis); @@ -88,6 +89,7 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) { assert(pThis != NULL); +dbgprintf("Terminate thread %d via method %d\n", pThis->thrdID, pThis->eTermTool); if(pThis->eTermTool == eTermSync_SIGNAL) { pthread_kill(pThis->thrdID, SIGUSR2); pthread_join(pThis->thrdID, NULL); @@ -101,6 +103,17 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) } +/* terminate all known threads gracefully. + */ +rsRetVal thrdTerminateAll(void) +{ +dbgprintf("thrdTerminateAll in\n"); + llDestroy(&llThrds); +dbgprintf("thrdTerminateAll out\n"); + return RS_RET_OK; +} + + /* Start a new thread and add it to the list of currently * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 @@ -115,6 +128,7 @@ rsRetVal thrdCreate(void* (*thrdMain)(void*)) CHKiRet(thrdConstruct(&pThis)); i = pthread_create(&pThis->thrdID, NULL, thrdMain, NULL); + CHKiRet(llAppend(&llThrds, NULL, pThis)); finalize_it: return iRet; -- cgit v1.2.3 From e45bbf5c66b5cb08c91bdb99ba1acf5f215c3112 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 14 Dec 2007 17:58:12 +0000 Subject: graceful termination now supported --- threads.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 96911403..139cf835 100644 --- a/threads.c +++ b/threads.c @@ -118,7 +118,7 @@ dbgprintf("thrdTerminateAll out\n"); * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(void* (*thrdMain)(void*)) +rsRetVal thrdCreate(void* (*thrdMain)(void*), eTermSyncType_t eTermSyncType) { DEFiRet; thrdInfo_t *pThis; @@ -127,6 +127,8 @@ rsRetVal thrdCreate(void* (*thrdMain)(void*)) assert(thrdMain != NULL); CHKiRet(thrdConstruct(&pThis)); + pThis->eTermTool = eTermSyncType; + pThis->bIsActive = 1; i = pthread_create(&pThis->thrdID, NULL, thrdMain, NULL); CHKiRet(llAppend(&llThrds, NULL, pThis)); @@ -135,15 +137,31 @@ finalize_it: } +/* This is a dummy handler. We user SIGUSR2 to interrupt blocking system calls + * if we are in termination mode 1. + */ +static void sigusr2Dummy(int sig) +{ + dbgprintf("sigusr2Dummy called!\n"); +} + + /* initialize the thread-support subsystem * must be called once at the start of the program */ rsRetVal thrdInit(void) { DEFiRet; + struct sigaction sigAct; iRet = llInit(&llThrds, thrdDestruct, NULL, NULL); + /* set up our termination subsystem */ + memset(&sigAct, 0, sizeof (sigAct)); + sigemptyset(&sigAct.sa_mask); + sigAct.sa_handler = sigusr2Dummy; + sigaction(SIGUSR2, &sigAct, NULL); + return iRet; } -- cgit v1.2.3 From b0ee8aac88dfad1a2d7c47f49670e52b368fa580 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 17 Dec 2007 07:46:30 +0000 Subject: created thread-class internal wrapper for calling user supplied thread main function --- threads.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 139cf835..dfe392fc 100644 --- a/threads.c +++ b/threads.c @@ -89,7 +89,7 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) { assert(pThis != NULL); -dbgprintf("Terminate thread %d via method %d\n", pThis->thrdID, pThis->eTermTool); +dbgprintf("Terminate thread %lx via method %d\n", pThis->thrdID, pThis->eTermTool); if(pThis->eTermTool == eTermSync_SIGNAL) { pthread_kill(pThis->thrdID, SIGUSR2); pthread_join(pThis->thrdID, NULL); @@ -114,11 +114,29 @@ dbgprintf("thrdTerminateAll out\n"); } +/* This is an internal wrapper around the user thread function. Its + * purpose is to handle all the necessary housekeeping stuff so that the + * user function needs not to be aware of the threading calls. The user + * function call has just "normal", non-threading semantics. + * rgerhards, 2007-12-17 + */ +static void* thrdStarter(void *arg) +{ + DEFiRet; + thrdInfo_t *pThis = (thrdInfo_t*) arg; + + assert(pThis != NULL); + assert(pThis->pUsrThrdMain != NULL); + iRet = pThis->pUsrThrdMain(); + dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d.\n", (unsigned long) pThis->thrdID, iRet); + pthread_exit(0); +} + /* Start a new thread and add it to the list of currently * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(void* (*thrdMain)(void*), eTermSyncType_t eTermSyncType) +rsRetVal thrdCreate(rsRetVal (*thrdMain)(void), eTermSyncType_t eTermSyncType) { DEFiRet; thrdInfo_t *pThis; @@ -129,7 +147,8 @@ rsRetVal thrdCreate(void* (*thrdMain)(void*), eTermSyncType_t eTermSyncType) CHKiRet(thrdConstruct(&pThis)); pThis->eTermTool = eTermSyncType; pThis->bIsActive = 1; - i = pthread_create(&pThis->thrdID, NULL, thrdMain, NULL); + pThis->pUsrThrdMain = thrdMain; + i = pthread_create(&pThis->thrdID, NULL, thrdStarter, pThis); CHKiRet(llAppend(&llThrds, NULL, pThis)); finalize_it: @@ -140,7 +159,7 @@ finalize_it: /* This is a dummy handler. We user SIGUSR2 to interrupt blocking system calls * if we are in termination mode 1. */ -static void sigusr2Dummy(int sig) +static void sigusr2Dummy(int __attribute__((unused)) sig) { dbgprintf("sigusr2Dummy called!\n"); } -- cgit v1.2.3 From 18dbfe70d804f6436658e8dd0af79188333e165a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 17 Dec 2007 09:06:23 +0000 Subject: moved thread termination code out to threads.c --- threads.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index dfe392fc..70271ab1 100644 --- a/threads.c +++ b/threads.c @@ -91,7 +91,8 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) dbgprintf("Terminate thread %lx via method %d\n", pThis->thrdID, pThis->eTermTool); if(pThis->eTermTool == eTermSync_SIGNAL) { - pthread_kill(pThis->thrdID, SIGUSR2); + pThis->bShallStop = 1; /* request termination */ + pthread_kill(pThis->thrdID, SIGUSR2); /* get thread out ouf blocking calls */ pthread_join(pThis->thrdID, NULL); /* TODO: TIMEOUT! */ } else if(pThis->eTermTool == eTermSync_NONE) { @@ -127,8 +128,22 @@ static void* thrdStarter(void *arg) assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); - iRet = pThis->pUsrThrdMain(); - dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d.\n", (unsigned long) pThis->thrdID, iRet); + + /* block all signals except the one we need for graceful termination */ + sigset_t sigSet; + sigfillset(&sigSet); + pthread_sigmask(SIG_BLOCK, &sigSet, NULL); + sigemptyset(&sigSet); + sigaddset(&sigSet, SIGUSR2); + pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL); + + /* setup complete, we are now ready to execute the user code. We will not + * regain control until the user code is finished, in which case we terminate + * the thread. + */ + iRet = pThis->pUsrThrdMain(pThis); + + dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d, exiting now.\n", (unsigned long) pThis->thrdID, iRet); pthread_exit(0); } @@ -136,7 +151,7 @@ static void* thrdStarter(void *arg) * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(rsRetVal (*thrdMain)(void), eTermSyncType_t eTermSyncType) +rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), eTermSyncType_t eTermSyncType) { DEFiRet; thrdInfo_t *pThis; @@ -198,6 +213,29 @@ rsRetVal thrdExit(void) } +/* thrdSleep() - a fairly portable way to put a thread to sleep. It + * will wake up when + * a) the wake-time is over + * b) the thread shall be terminated + * Returns RS_RET_OK if all went well, RS_RET_TERMINATE_NOW if the calling + * thread shall be terminated and any other state if an error happened. + * rgerhards, 2007-12-17 + */ +rsRetVal +thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) +{ + DEFiRet; + struct timeval tvSelectTimeout; + + assert(pThis != NULL); + tvSelectTimeout.tv_sec = iSeconds; + tvSelectTimeout.tv_usec = iuSeconds; /* micro seconds */ + select(0, NULL, NULL, NULL, &tvSelectTimeout); + if(pThis->bShallStop) + iRet = RS_RET_TERMINATE_NOW; + return iRet; +} + /* queue functions (may be migrated to some other file...) */ -- cgit v1.2.3 From 653ec62b23346eaab4f2f3830eeb7f1634a924c5 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 17 Dec 2007 14:34:22 +0000 Subject: - implemented afterRun input module interface function - implemented $klogSymbolsTwice config directive --- threads.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 70271ab1..88b4ce8f 100644 --- a/threads.c +++ b/threads.c @@ -99,6 +99,10 @@ dbgprintf("Terminate thread %lx via method %d\n", pThis->thrdID, pThis->eTermToo pthread_cancel(pThis->thrdID); } pThis->bIsActive = 0; + + /* call cleanup function, if any */ + if(pThis->pAfterRun != NULL) + pThis->pAfterRun(pThis); return RS_RET_OK; } @@ -108,9 +112,7 @@ dbgprintf("Terminate thread %lx via method %d\n", pThis->thrdID, pThis->eTermToo */ rsRetVal thrdTerminateAll(void) { -dbgprintf("thrdTerminateAll in\n"); llDestroy(&llThrds); -dbgprintf("thrdTerminateAll out\n"); return RS_RET_OK; } @@ -151,7 +153,7 @@ static void* thrdStarter(void *arg) * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), eTermSyncType_t eTermSyncType) +rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), eTermSyncType_t eTermSyncType, rsRetVal(*afterRun)(thrdInfo_t *)) { DEFiRet; thrdInfo_t *pThis; @@ -163,6 +165,7 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), eTermSyncType_t eTermSync pThis->eTermTool = eTermSyncType; pThis->bIsActive = 1; pThis->pUsrThrdMain = thrdMain; + pThis->pAfterRun = afterRun; i = pthread_create(&pThis->thrdID, NULL, thrdStarter, pThis); CHKiRet(llAppend(&llThrds, NULL, pThis)); -- cgit v1.2.3 From 2eb19201b3f4be01057c1b958a077b5fb2fce107 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 20 Dec 2007 08:54:51 +0000 Subject: - working on a potential race condition on the new input module interface. See newsgroup posting for details on the issue: http://groups.google.com/group/comp.programming.threads/msg/330b9675f17 a1ad6 I tried some mutex operations but came to the conclusion that this does not really help. So I have now switched to plain thread cancellation, which so far seems to be OK. Need more practical experience with other input modules to make a final decision. Thus I leave all code in and have just disabled the problematic code. --- threads.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 88b4ce8f..04eea8f1 100644 --- a/threads.c +++ b/threads.c @@ -1,3 +1,7 @@ +/* TODO: we should guard the individual thread actions with a mutex. Else, we may + * run into race conditions on thread termination. + */ + /* threads.c * * This file implements threading support helpers (and maybe the thread object) @@ -25,7 +29,6 @@ * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" -#include "rsyslog.h" #include #include @@ -33,6 +36,7 @@ #include #include +#include "rsyslog.h" #include "syslogd.h" #include "linkedlist.h" #include "threads.h" @@ -48,18 +52,22 @@ static linkedList_t llThrds; /* Construct a new thread object */ -static rsRetVal thrdConstruct(thrdInfo_t **pThis) +static rsRetVal thrdConstruct(thrdInfo_t **ppThis) { - thrdInfo_t *pNew; + thrdInfo_t *pThis; + + assert(ppThis != NULL); - if((pNew = calloc(1, sizeof(thrdInfo_t))) == NULL) + if((pThis = calloc(1, sizeof(thrdInfo_t))) == NULL) return RS_RET_OUT_OF_MEMORY; /* OK, we got the element, now initialize members that should * not be zero-filled. */ + pThis->mutTermOK = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t)); + pthread_mutex_init (pThis->mutTermOK, NULL); - *pThis = pNew; + *ppThis = pThis; return RS_RET_OK; } @@ -76,6 +84,7 @@ dbgprintf("thrdDestruct, pThis: %lx\n", pThis); if(pThis->bIsActive == 1) { thrdTerminate(pThis); } + free(pThis->mutTermOK); free(pThis); return RS_RET_OK; @@ -91,9 +100,15 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) dbgprintf("Terminate thread %lx via method %d\n", pThis->thrdID, pThis->eTermTool); if(pThis->eTermTool == eTermSync_SIGNAL) { + /* we first wait for the thread to reach a point in execution where it + * is safe to terminate it. + * TODO: TIMEOUT! + */ + pthread_mutex_lock(pThis->mutTermOK); pThis->bShallStop = 1; /* request termination */ pthread_kill(pThis->thrdID, SIGUSR2); /* get thread out ouf blocking calls */ pthread_join(pThis->thrdID, NULL); + pthread_mutex_unlock(pThis->mutTermOK); /* cleanup... */ /* TODO: TIMEOUT! */ } else if(pThis->eTermTool == eTermSync_NONE) { pthread_cancel(pThis->thrdID); @@ -162,7 +177,7 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), eTermSyncType_t eTermSync assert(thrdMain != NULL); CHKiRet(thrdConstruct(&pThis)); - pThis->eTermTool = eTermSyncType; + pThis->eTermTool = eTermSync_NONE; // eTermSyncType; TODO: review pThis->bIsActive = 1; pThis->pUsrThrdMain = thrdMain; pThis->pAfterRun = afterRun; @@ -233,9 +248,15 @@ thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) assert(pThis != NULL); tvSelectTimeout.tv_sec = iSeconds; tvSelectTimeout.tv_usec = iuSeconds; /* micro seconds */ + thrdUnblockTermination(pThis); + /* there may be a race condition if pthread_kill() is called after unblock but + * before the select() is setup. TODO: check and re-eval -- rgerhards, 2007-12-20 + */ select(0, NULL, NULL, NULL, &tvSelectTimeout); if(pThis->bShallStop) iRet = RS_RET_TERMINATE_NOW; + else + thrdBlockTermination(pThis); return iRet; } -- cgit v1.2.3 From ab94b8a7fdad8b00a957ec28ef0ab904184fd8fb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 20 Dec 2007 10:23:40 +0000 Subject: fixed race condition --- threads.c | 1 + 1 file changed, 1 insertion(+) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 04eea8f1..ea79c380 100644 --- a/threads.c +++ b/threads.c @@ -112,6 +112,7 @@ dbgprintf("Terminate thread %lx via method %d\n", pThis->thrdID, pThis->eTermToo /* TODO: TIMEOUT! */ } else if(pThis->eTermTool == eTermSync_NONE) { pthread_cancel(pThis->thrdID); + pthread_join(pThis->thrdID, NULL); /* wait for cancel to complete */ } pThis->bIsActive = 0; -- cgit v1.2.3 From c26059ea2689f5331f9820caf92a8a52a5006bfc Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 21 Dec 2007 16:25:55 +0000 Subject: removed code no longer needed --- threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index ea79c380..ea0fb19b 100644 --- a/threads.c +++ b/threads.c @@ -253,7 +253,7 @@ thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) /* there may be a race condition if pthread_kill() is called after unblock but * before the select() is setup. TODO: check and re-eval -- rgerhards, 2007-12-20 */ - select(0, NULL, NULL, NULL, &tvSelectTimeout); + select(1, NULL, NULL, NULL, &tvSelectTimeout); if(pThis->bShallStop) iRet = RS_RET_TERMINATE_NOW; else -- cgit v1.2.3 From 7af2c0a66b03db92a9ca1faae6c37c8fdc666c0e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 25 Dec 2007 15:49:57 +0000 Subject: moved udp net code - again, stage work --- threads.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'threads.c') diff --git a/threads.c b/threads.c index ea0fb19b..4b86534d 100644 --- a/threads.c +++ b/threads.c @@ -256,8 +256,10 @@ thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) select(1, NULL, NULL, NULL, &tvSelectTimeout); if(pThis->bShallStop) iRet = RS_RET_TERMINATE_NOW; +#if 0 /* TODO: remove once we know we do not need the thrdBlockTermination() call -- rgerhards, 2007.12.25 */ else thrdBlockTermination(pThis); +#endif return iRet; } -- cgit v1.2.3 From cebbf6d44ef277c7349fec19e70f93915b351e2a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 27 Dec 2007 14:29:09 +0000 Subject: some cleanup --- threads.c | 1 - 1 file changed, 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 4b86534d..38e86195 100644 --- a/threads.c +++ b/threads.c @@ -79,7 +79,6 @@ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) static rsRetVal thrdDestruct(thrdInfo_t *pThis) { assert(pThis != NULL); -dbgprintf("thrdDestruct, pThis: %lx\n", pThis); if(pThis->bIsActive == 1) { thrdTerminate(pThis); -- cgit v1.2.3 From 29d9729292d44d2827054a1aef27278f3dadd57e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 3 Jan 2008 09:44:54 +0000 Subject: moved queue code to its own module (finally) --- threads.c | 88 --------------------------------------------------------------- 1 file changed, 88 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 38e86195..24cae97f 100644 --- a/threads.c +++ b/threads.c @@ -41,10 +41,6 @@ #include "linkedlist.h" #include "threads.h" -/* static data */ -int iMainMsgQueueSize; -msgQueue *pMsgQueue = NULL; - /* linked list of currently-known threads */ static linkedList_t llThrds; @@ -263,90 +259,6 @@ thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) } -/* queue functions (may be migrated to some other file...) - */ - - -msgQueue *queueInit (void) -{ - msgQueue *q; - - q = (msgQueue *)malloc(sizeof(msgQueue)); - if (q == NULL) return (NULL); - if((q->pbuf = malloc(sizeof(void *) * iMainMsgQueueSize)) == NULL) { - free(q); - return NULL; - } - - q->empty = 1; - q->full = 0; - q->head = 0; - q->tail = 0; - q->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t)); - pthread_mutex_init (q->mut, NULL); - q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); - pthread_cond_init (q->notFull, NULL); - q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); - pthread_cond_init (q->notEmpty, NULL); - - return (q); -} - -void queueDelete (msgQueue *q) -{ - pthread_mutex_destroy (q->mut); - free (q->mut); - pthread_cond_destroy (q->notFull); - free (q->notFull); - pthread_cond_destroy (q->notEmpty); - free (q->notEmpty); - free(q->pbuf); - free (q); -} - - -/* In queueAdd() and queueDel() we have a potential race condition. If a message - * is dequeued and at the same time a message is enqueued and the queue is either - * full or empty, the full (or empty) indicator may be invalidly updated. HOWEVER, - * this does not cause any real problems. No queue pointers can be wrong. And even - * if one of the flags is set invalidly, that does not pose a real problem. If - * "full" is invalidly set, at mose one message might be lost, if we are already in - * a timeout situation (this is quite acceptable). And if "empty" is accidently set, - * the receiver will not continue the inner loop, but break out of the outer. So no - * harm is done at all. For this reason, I do not yet use a mutex to guard the two - * flags - there would be a notable performance hit with, IMHO, no gain in stability - * or functionality. But anyhow, now it's documented... - * rgerhards, 2007-09-20 - * NOTE: this comment does not really apply - the callers handle the mutex, so it - * *is* guarded. - */ -void queueAdd (msgQueue *q, void* in) -{ - q->pbuf[q->tail] = in; - q->tail++; - if (q->tail == iMainMsgQueueSize) - q->tail = 0; - if (q->tail == q->head) - q->full = 1; - q->empty = 0; - - return; -} - -void queueDel(msgQueue *q, void **out) -{ - *out = (void*) q->pbuf[q->head]; - - q->head++; - if (q->head == iMainMsgQueueSize) - q->head = 0; - if (q->head == q->tail) - q->empty = 1; - q->full = 0; - - return; -} - /* * vi:set ai: */ -- cgit v1.2.3 From 28c44e9a7bf4f99279af94a96bac42d0379b27d0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 10 Jan 2008 14:27:26 +0000 Subject: - fixed a bug that caused a segfault on startup when no $WorkDir directive was specified in rsyslog.conf - fixed a bug that caused a segfault on queues with types other than "disk" - removed the now longer needed thread TermSyncTool --- threads.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 24cae97f..2166f4bb 100644 --- a/threads.c +++ b/threads.c @@ -86,29 +86,15 @@ static rsRetVal thrdDestruct(thrdInfo_t *pThis) } -/* terminate a thread gracefully. It's termination sync state is taken into - * account. +/* terminate a thread gracefully. */ rsRetVal thrdTerminate(thrdInfo_t *pThis) { assert(pThis != NULL); -dbgprintf("Terminate thread %lx via method %d\n", pThis->thrdID, pThis->eTermTool); - if(pThis->eTermTool == eTermSync_SIGNAL) { - /* we first wait for the thread to reach a point in execution where it - * is safe to terminate it. - * TODO: TIMEOUT! - */ - pthread_mutex_lock(pThis->mutTermOK); - pThis->bShallStop = 1; /* request termination */ - pthread_kill(pThis->thrdID, SIGUSR2); /* get thread out ouf blocking calls */ - pthread_join(pThis->thrdID, NULL); - pthread_mutex_unlock(pThis->mutTermOK); /* cleanup... */ - /* TODO: TIMEOUT! */ - } else if(pThis->eTermTool == eTermSync_NONE) { - pthread_cancel(pThis->thrdID); - pthread_join(pThis->thrdID, NULL); /* wait for cancel to complete */ - } +dbgprintf("Terminate thread %lx\n", pThis->thrdID); + pthread_cancel(pThis->thrdID); + pthread_join(pThis->thrdID, NULL); /* wait for cancel to complete */ pThis->bIsActive = 0; /* call cleanup function, if any */ @@ -164,7 +150,7 @@ static void* thrdStarter(void *arg) * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), eTermSyncType_t eTermSyncType, rsRetVal(*afterRun)(thrdInfo_t *)) +rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *)) { DEFiRet; thrdInfo_t *pThis; @@ -173,7 +159,6 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), eTermSyncType_t eTermSync assert(thrdMain != NULL); CHKiRet(thrdConstruct(&pThis)); - pThis->eTermTool = eTermSync_NONE; // eTermSyncType; TODO: review pThis->bIsActive = 1; pThis->pUsrThrdMain = thrdMain; pThis->pAfterRun = afterRun; -- cgit v1.2.3 From 68efb41220a834870681f293481655ed47e7b197 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 10 Jan 2008 17:33:21 +0000 Subject: - some cleanup - implemented management function for worker thread 0 in order to change queue workers dynamically -- stage work --- threads.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 2166f4bb..8ce5515d 100644 --- a/threads.c +++ b/threads.c @@ -229,17 +229,9 @@ thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) assert(pThis != NULL); tvSelectTimeout.tv_sec = iSeconds; tvSelectTimeout.tv_usec = iuSeconds; /* micro seconds */ - thrdUnblockTermination(pThis); - /* there may be a race condition if pthread_kill() is called after unblock but - * before the select() is setup. TODO: check and re-eval -- rgerhards, 2007-12-20 - */ select(1, NULL, NULL, NULL, &tvSelectTimeout); if(pThis->bShallStop) iRet = RS_RET_TERMINATE_NOW; -#if 0 /* TODO: remove once we know we do not need the thrdBlockTermination() call -- rgerhards, 2007.12.25 */ - else - thrdBlockTermination(pThis); -#endif return iRet; } -- cgit v1.2.3 From 5c686c8adcc473cbdbb14e4b2d736f9123210ee6 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 24 Jan 2008 17:55:09 +0000 Subject: redesigned queue to utilize helper classes for threading support. This is finally in a running state for regular (non disk-assisted) queues, with a minor nit at shutdown. So I can finally commit the work again to CVS... --- threads.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 8ce5515d..c7b5f4e4 100644 --- a/threads.c +++ b/threads.c @@ -143,6 +143,7 @@ static void* thrdStarter(void *arg) iRet = pThis->pUsrThrdMain(pThis); dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d, exiting now.\n", (unsigned long) pThis->thrdID, iRet); + ENDfunc pthread_exit(0); } @@ -166,7 +167,7 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdI CHKiRet(llAppend(&llThrds, NULL, pThis)); finalize_it: - return iRet; + RETiRet; } @@ -195,7 +196,7 @@ rsRetVal thrdInit(void) sigAct.sa_handler = sigusr2Dummy; sigaction(SIGUSR2, &sigAct, NULL); - return iRet; + RETiRet; } @@ -208,7 +209,7 @@ rsRetVal thrdExit(void) iRet = llDestroy(&llThrds); - return iRet; + RETiRet; } @@ -232,7 +233,7 @@ thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) select(1, NULL, NULL, NULL, &tvSelectTimeout); if(pThis->bShallStop) iRet = RS_RET_TERMINATE_NOW; - return iRet; + RETiRet; } -- cgit v1.2.3 From a914e3164e5c9522b6ac9a39327ed46628d3e045 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 18 Feb 2008 10:41:07 +0000 Subject: - removed no longer necessary signal from threads.c - changed debug output request signal to SIGUSR2 (as originally intented), restored SIGUSR1 semantics --- threads.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index c7b5f4e4..5933d3e5 100644 --- a/threads.c +++ b/threads.c @@ -1,7 +1,3 @@ -/* TODO: we should guard the individual thread actions with a mutex. Else, we may - * run into race conditions on thread termination. - */ - /* threads.c * * This file implements threading support helpers (and maybe the thread object) @@ -128,13 +124,10 @@ static void* thrdStarter(void *arg) assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); - /* block all signals except the one we need for graceful termination */ + /* block all signalsi */ sigset_t sigSet; sigfillset(&sigSet); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); - sigemptyset(&sigSet); - sigaddset(&sigSet, SIGUSR2); - pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL); /* setup complete, we are now ready to execute the user code. We will not * regain control until the user code is finished, in which case we terminate @@ -171,31 +164,13 @@ finalize_it: } -/* This is a dummy handler. We user SIGUSR2 to interrupt blocking system calls - * if we are in termination mode 1. - */ -static void sigusr2Dummy(int __attribute__((unused)) sig) -{ - dbgprintf("sigusr2Dummy called!\n"); -} - - /* initialize the thread-support subsystem * must be called once at the start of the program */ rsRetVal thrdInit(void) { DEFiRet; - struct sigaction sigAct; - iRet = llInit(&llThrds, thrdDestruct, NULL, NULL); - - /* set up our termination subsystem */ - memset(&sigAct, 0, sizeof (sigAct)); - sigemptyset(&sigAct.sa_mask); - sigAct.sa_handler = sigusr2Dummy; - sigaction(SIGUSR2, &sigAct, NULL); - RETiRet; } -- cgit v1.2.3 From 52ac1ab34c257731efa237191ea765029d7fc8b5 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 6 Mar 2008 11:20:36 +0000 Subject: worked some more on HP UX - got it to compile and receive UDP messages --- threads.c | 1 - 1 file changed, 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 5933d3e5..e32ff0d9 100644 --- a/threads.c +++ b/threads.c @@ -88,7 +88,6 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) { assert(pThis != NULL); -dbgprintf("Terminate thread %lx\n", pThis->thrdID); pthread_cancel(pThis->thrdID); pthread_join(pThis->thrdID, NULL); /* wait for cancel to complete */ pThis->bIsActive = 0; -- cgit v1.2.3 From d9b0c77d3e719d4c08361e62f3b067228c30f6a9 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 16 Apr 2008 15:27:53 +0200 Subject: some more cleanup reduced dependencies, moved non-runtime files to its own directory except for some whom's status is unclear --- threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index e32ff0d9..f4f604fc 100644 --- a/threads.c +++ b/threads.c @@ -33,7 +33,7 @@ #include #include "rsyslog.h" -#include "syslogd.h" +#include "dirty.h" #include "linkedlist.h" #include "threads.h" -- cgit v1.2.3 From 7b456ce548030ff362d3a2be04b1e5c2c89e0dcb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 14 Aug 2008 11:19:02 +0200 Subject: bugfix: imfile could cause a segfault upon rsyslogd HUP and termination Thanks to lperr for an excellent bug report that helped detect this problem. --- threads.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index e32ff0d9..03f19ff9 100644 --- a/threads.c +++ b/threads.c @@ -46,6 +46,7 @@ static linkedList_t llThrds; */ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) { + DEFiRet; thrdInfo_t *pThis; assert(ppThis != NULL); @@ -60,7 +61,7 @@ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) pthread_mutex_init (pThis->mutTermOK, NULL); *ppThis = pThis; - return RS_RET_OK; + RETiRet; } @@ -70,6 +71,7 @@ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) */ static rsRetVal thrdDestruct(thrdInfo_t *pThis) { + DEFiRet; assert(pThis != NULL); if(pThis->bIsActive == 1) { @@ -78,7 +80,7 @@ static rsRetVal thrdDestruct(thrdInfo_t *pThis) free(pThis->mutTermOK); free(pThis); - return RS_RET_OK; + RETiRet; } @@ -86,6 +88,7 @@ static rsRetVal thrdDestruct(thrdInfo_t *pThis) */ rsRetVal thrdTerminate(thrdInfo_t *pThis) { + DEFiRet; assert(pThis != NULL); pthread_cancel(pThis->thrdID); @@ -96,7 +99,7 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) if(pThis->pAfterRun != NULL) pThis->pAfterRun(pThis); - return RS_RET_OK; + RETiRet; } @@ -104,8 +107,9 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) */ rsRetVal thrdTerminateAll(void) { + DEFiRet; llDestroy(&llThrds); - return RS_RET_OK; + RETiRet; } -- cgit v1.2.3 From 7b63cd6feda5087c43652bdcf8e694b544295d5b Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 18 Sep 2008 12:44:00 +0200 Subject: minor things, mostly improved debug info --- threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 61ea8f29..13222694 100644 --- a/threads.c +++ b/threads.c @@ -127,7 +127,7 @@ static void* thrdStarter(void *arg) assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); - /* block all signalsi */ + /* block all signals */ sigset_t sigSet; sigfillset(&sigSet); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); -- cgit v1.2.3 From 7d92de155c832e0a4af2cb3b65f7cef909b19f8d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 20 Jul 2009 18:36:30 +0200 Subject: internal: added ability to terminate input modules not via pthread_cancel... ... but an alternate approach via pthread_kill. This is somewhat safer as we do not need to think about the cancel-safeness of all libraries we use. However, not all inputs can easily supported, so this now is a feature that can be requested by the input module (the most important ones request it). --- threads.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 13222694..20ab9f66 100644 --- a/threads.c +++ b/threads.c @@ -51,8 +51,7 @@ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) assert(ppThis != NULL); - if((pThis = calloc(1, sizeof(thrdInfo_t))) == NULL) - return RS_RET_OUT_OF_MEMORY; + CHKmalloc(pThis = calloc(1, sizeof(thrdInfo_t))); /* OK, we got the element, now initialize members that should * not be zero-filled. @@ -61,6 +60,8 @@ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) pthread_mutex_init (pThis->mutTermOK, NULL); *ppThis = pThis; + +finalize_it: RETiRet; } @@ -91,8 +92,14 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) DEFiRet; assert(pThis != NULL); - pthread_cancel(pThis->thrdID); - pthread_join(pThis->thrdID, NULL); /* wait for cancel to complete */ + if(pThis->bNeedsCancel) { + DBGPRINTF("request term via canceling for input thread 0x%x\n", (unsigned) pThis->thrdID); + pthread_cancel(pThis->thrdID); + } else { + DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID); + pthread_kill(pThis->thrdID, SIGTTIN); + } + pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */ pThis->bIsActive = 0; /* call cleanup function, if any */ @@ -132,6 +139,11 @@ static void* thrdStarter(void *arg) sigfillset(&sigSet); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); + /* but ignore SIGTTN, which we (ab)use to signal the thread to shutdown -- rgerhards, 2009-07-20 */ + sigemptyset(&sigSet); + sigaddset(&sigSet, SIGTTIN); + pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL); + /* setup complete, we are now ready to execute the user code. We will not * regain control until the user code is finished, in which case we terminate * the thread. @@ -147,7 +159,7 @@ static void* thrdStarter(void *arg) * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *)) +rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), bool bNeedsCancel) { DEFiRet; thrdInfo_t *pThis; @@ -159,6 +171,7 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdI pThis->bIsActive = 1; pThis->pUsrThrdMain = thrdMain; pThis->pAfterRun = afterRun; + pThis->bNeedsCancel = bNeedsCancel; i = pthread_create(&pThis->thrdID, NULL, thrdStarter, pThis); CHKiRet(llAppend(&llThrds, NULL, pThis)); -- cgit v1.2.3 From a5e8684b91bf88c53f4afb548b797ac9ccb463e2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 20 Jul 2009 19:01:03 +0200 Subject: disabling new input termination interface a bug showed up during further testing. As this was a side-activity, I'll probably disable it for the time being and check what's going on somewhat later (I'll do it tomorrow if I can find it quickly) --- threads.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 20ab9f66..05e6159f 100644 --- a/threads.c +++ b/threads.c @@ -92,13 +92,19 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) DEFiRet; assert(pThis != NULL); +#if 0 // TODO: somehow does not really work yet! if(pThis->bNeedsCancel) { +#endif DBGPRINTF("request term via canceling for input thread 0x%x\n", (unsigned) pThis->thrdID); pthread_cancel(pThis->thrdID); +#if 0 // TODO: somehow does not really work yet! + if(pThis->bNeedsCancel) { } else { + DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID); pthread_kill(pThis->thrdID, SIGTTIN); } +#endif pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */ pThis->bIsActive = 0; -- cgit v1.2.3 From 08fca4477cf525cada8c66d309ea1daa2eac88b2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 12 Oct 2009 17:10:04 +0200 Subject: re-enabled input thread termination handling that does avoid thread cancellation ...where possible. This provides a more reliable mode of rsyslogd termination (canceling threads my result in not properly freed resouces and potential later hangs, even though we perform proper cancel handling in our code). This is part of an effort to reduce thread cnacellation as much as possible in rsyslog. NOTE: some comments indicated that there were problems with some code that has been re-activated. Testing did not show any issues. My current assumption is that these issues were related to some other code that has been removed/changed during the previous restructuring events. In any case, if there is a shutdown issue, one should carefully look at this change here! --- threads.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 05e6159f..a6cbc2ff 100644 --- a/threads.c +++ b/threads.c @@ -92,19 +92,14 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) DEFiRet; assert(pThis != NULL); -#if 0 // TODO: somehow does not really work yet! if(pThis->bNeedsCancel) { -#endif DBGPRINTF("request term via canceling for input thread 0x%x\n", (unsigned) pThis->thrdID); pthread_cancel(pThis->thrdID); -#if 0 // TODO: somehow does not really work yet! - if(pThis->bNeedsCancel) { } else { DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID); pthread_kill(pThis->thrdID, SIGTTIN); } -#endif pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */ pThis->bIsActive = 0; -- cgit v1.2.3 From e53d91ce666453b114880e0619dd8c4d40072201 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 15 Oct 2009 18:33:33 +0200 Subject: solved a recently introduced race during input thread shutdown This was introduced when we re-enabled non-cancel thread termination a few commits ago. This code has never been released as a tarball, so that is no bugfix for a release but rather a WiP regression fix and thus does not need to be mentioned in the ChangeLog. --- threads.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 18 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index a6cbc2ff..b8c19ed2 100644 --- a/threads.c +++ b/threads.c @@ -5,7 +5,7 @@ * * File begun on 2007-12-14 by RGerhards * - * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007, 2009 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,7 @@ #include "dirty.h" #include "linkedlist.h" #include "threads.h" +#include "srUtils.h" /* linked list of currently-known threads */ static linkedList_t llThrds; @@ -44,7 +46,8 @@ static linkedList_t llThrds; /* Construct a new thread object */ -static rsRetVal thrdConstruct(thrdInfo_t **ppThis) +static rsRetVal +thrdConstruct(thrdInfo_t **ppThis) { DEFiRet; thrdInfo_t *pThis; @@ -52,13 +55,8 @@ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) assert(ppThis != NULL); CHKmalloc(pThis = calloc(1, sizeof(thrdInfo_t))); - - /* OK, we got the element, now initialize members that should - * not be zero-filled. - */ - pThis->mutTermOK = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t)); - pthread_mutex_init (pThis->mutTermOK, NULL); - + pthread_mutex_init(&pThis->mutThrd, NULL); + pthread_cond_init(&pThis->condThrdTerm, NULL); *ppThis = pThis; finalize_it: @@ -78,13 +76,54 @@ static rsRetVal thrdDestruct(thrdInfo_t *pThis) if(pThis->bIsActive == 1) { thrdTerminate(pThis); } - free(pThis->mutTermOK); + pthread_mutex_destroy(&pThis->mutThrd); + pthread_cond_destroy(&pThis->condThrdTerm); free(pThis); RETiRet; } +/* terminate a thread via the non-cancel interface + * This is a separate function as it involves a bit more of code. + * rgerhads, 2009-10-15 + */ +static inline rsRetVal +thrdTerminateNonCancel(thrdInfo_t *pThis) +{ + struct timespec tTimeout; + int ret; + DEFiRet; + assert(pThis != NULL); + + DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID); + pThis->bShallStop = TRUE; + do { + d_pthread_mutex_lock(&pThis->mutThrd); + pthread_kill(pThis->thrdID, SIGTTIN); + timeoutComp(&tTimeout, 10); /* a fixed 10ms timeout, do after lock (may take long!) */ + ret = d_pthread_cond_timedwait(&pThis->condThrdTerm, &pThis->mutThrd, &tTimeout); + d_pthread_mutex_unlock(&pThis->mutThrd); + if(Debug) { + if(ret == ETIMEDOUT) { + dbgprintf("input thread term: had a timeout waiting on thread termination\n"); + } else if(ret == 0) { + dbgprintf("input thread term: thread returned normally and is terminated\n"); + } else { + char errStr[1024]; + int err = errno; + rs_strerror_r(err, errStr, sizeof(errStr)); + dbgprintf("input thread term: cond_wait returned with error %d: %s\n", + err, errStr); + } + } + } while(pThis->bIsActive); + DBGPRINTF("non-cancel input thread termination succeeded for thread 0x%x\n", (unsigned) pThis->thrdID); + + RETiRet; +} + + /* terminate a thread gracefully. */ rsRetVal thrdTerminate(thrdInfo_t *pThis) @@ -95,13 +134,11 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis) if(pThis->bNeedsCancel) { DBGPRINTF("request term via canceling for input thread 0x%x\n", (unsigned) pThis->thrdID); pthread_cancel(pThis->thrdID); + pThis->bIsActive = 0; } else { - - DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID); - pthread_kill(pThis->thrdID, SIGTTIN); + thrdTerminateNonCancel(pThis); } pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */ - pThis->bIsActive = 0; /* call cleanup function, if any */ if(pThis->pAfterRun != NULL) @@ -152,6 +189,16 @@ static void* thrdStarter(void *arg) iRet = pThis->pUsrThrdMain(pThis); dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d, exiting now.\n", (unsigned long) pThis->thrdID, iRet); + + /* signal master control that we exit (we do the mutex lock mostly to + * keep the thread debugger happer, it would not really be necessary with + * the logic we employ...) + */ + pThis->bIsActive = 0; + d_pthread_mutex_lock(&pThis->mutThrd); + pthread_cond_signal(&pThis->condThrdTerm); + d_pthread_mutex_unlock(&pThis->mutThrd); + ENDfunc pthread_exit(0); } @@ -198,9 +245,7 @@ rsRetVal thrdInit(void) rsRetVal thrdExit(void) { DEFiRet; - iRet = llDestroy(&llThrds); - RETiRet; } @@ -229,6 +274,5 @@ thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) } -/* - * vi:set ai: +/* vi:set ai: */ -- cgit v1.2.3 From e005c5569c3e0c7c9a098036b7ec3596c3c722b4 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 16 Oct 2009 09:42:36 +0200 Subject: some minor cleanup, consolidated some code --- threads.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index b8c19ed2..ccc80816 100644 --- a/threads.c +++ b/threads.c @@ -250,29 +250,5 @@ rsRetVal thrdExit(void) } -/* thrdSleep() - a fairly portable way to put a thread to sleep. It - * will wake up when - * a) the wake-time is over - * b) the thread shall be terminated - * Returns RS_RET_OK if all went well, RS_RET_TERMINATE_NOW if the calling - * thread shall be terminated and any other state if an error happened. - * rgerhards, 2007-12-17 - */ -rsRetVal -thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds) -{ - DEFiRet; - struct timeval tvSelectTimeout; - - assert(pThis != NULL); - tvSelectTimeout.tv_sec = iSeconds; - tvSelectTimeout.tv_usec = iuSeconds; /* micro seconds */ - select(1, NULL, NULL, NULL, &tvSelectTimeout); - if(pThis->bShallStop) - iRet = RS_RET_TERMINATE_NOW; - RETiRet; -} - - /* vi:set ai: */ -- cgit v1.2.3 From 38cb3926727c0ad29f3950db43ba12248e867b89 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 2 Feb 2010 15:51:01 +0100 Subject: replaced data type "bool" by "sbool" because this created some portability issues --- threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index ccc80816..4064fc7a 100644 --- a/threads.c +++ b/threads.c @@ -207,7 +207,7 @@ static void* thrdStarter(void *arg) * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), bool bNeedsCancel) +rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), sbool bNeedsCancel) { DEFiRet; thrdInfo_t *pThis; -- cgit v1.2.3 From 371a8eec29fa25bbf58f4b1f0d7e3bf4c3ad6329 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 16 Dec 2010 12:57:55 +0100 Subject: some cleanup based on clang static analyzer results --- threads.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 13222694..051903de 100644 --- a/threads.c +++ b/threads.c @@ -151,7 +151,6 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdI { DEFiRet; thrdInfo_t *pThis; - int i; assert(thrdMain != NULL); @@ -159,7 +158,7 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdI pThis->bIsActive = 1; pThis->pUsrThrdMain = thrdMain; pThis->pAfterRun = afterRun; - i = pthread_create(&pThis->thrdID, NULL, thrdStarter, pThis); + pthread_create(&pThis->thrdID, NULL, thrdStarter, pThis); CHKiRet(llAppend(&llThrds, NULL, pThis)); finalize_it: -- cgit v1.2.3 From 7742b2182fc017ca4c9fcfe3b26f4c8d68a9bd58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dra=C5=BEen=20Ka=C4=8Dar?= Date: Mon, 10 Jan 2011 12:39:23 +0100 Subject: improved imudp real-time scheduling support & bugfix The original code had quite some issues, which are fixed by this commit. Also we do more error checking now. Signed-off-by: Rainer Gerhards --- threads.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 4064fc7a..f1f275bd 100644 --- a/threads.c +++ b/threads.c @@ -220,7 +220,13 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdI pThis->pUsrThrdMain = thrdMain; pThis->pAfterRun = afterRun; pThis->bNeedsCancel = bNeedsCancel; - i = pthread_create(&pThis->thrdID, NULL, thrdStarter, pThis); + i = pthread_create(&pThis->thrdID, +#ifdef HAVE_PTHREAD_SETSCHEDPARAM + &default_thread_attr, +#else + NULL, +#endif + thrdStarter, pThis); CHKiRet(llAppend(&llThrds, NULL, pThis)); finalize_it: -- cgit v1.2.3 From f3d354da3e373f9c4890a78e5274a6ba02f1c8cb Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 11 Feb 2011 17:47:30 +0100 Subject: bugfix: very long running actions could prevent shutdown under some circumstances This has now been solved, at least for common situations. --- threads.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index d4e14527..fcafce4b 100644 --- a/threads.c +++ b/threads.c @@ -101,12 +101,14 @@ thrdTerminateNonCancel(thrdInfo_t *pThis) do { d_pthread_mutex_lock(&pThis->mutThrd); pthread_kill(pThis->thrdID, SIGTTIN); - timeoutComp(&tTimeout, 10); /* a fixed 10ms timeout, do after lock (may take long!) */ + timeoutComp(&tTimeout, 1000); /* a fixed 1sec timeout */ ret = d_pthread_cond_timedwait(&pThis->condThrdTerm, &pThis->mutThrd, &tTimeout); d_pthread_mutex_unlock(&pThis->mutThrd); if(Debug) { if(ret == ETIMEDOUT) { - dbgprintf("input thread term: had a timeout waiting on thread termination\n"); + dbgprintf("input thread term: timeout expired waiting on thread termination - canceling\n"); + pthread_cancel(pThis->thrdID); + pThis->bIsActive = 0; } else if(ret == 0) { dbgprintf("input thread term: thread returned normally and is terminated\n"); } else { -- cgit v1.2.3 From 39406781e51c7305cb9f35f5f9fed9c10dea9ecd Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 17 Feb 2011 15:12:54 +0100 Subject: bugfix: minor race condition in action.c - considered cosmetic This is considered cosmetic as multiple threads tried to write exactly the same value into the same memory location without sync. The method has been changed so this can no longer happen. --- threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index fcafce4b..11c9a1d8 100644 --- a/threads.c +++ b/threads.c @@ -196,8 +196,8 @@ static void* thrdStarter(void *arg) * keep the thread debugger happer, it would not really be necessary with * the logic we employ...) */ - pThis->bIsActive = 0; d_pthread_mutex_lock(&pThis->mutThrd); + pThis->bIsActive = 0; pthread_cond_signal(&pThis->condThrdTerm); d_pthread_mutex_unlock(&pThis->mutThrd); -- cgit v1.2.3 From 0216053099b6c93d595d41cdb9ef173c8687e6c2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 11 Jan 2012 18:30:33 +0100 Subject: relicense parts under ASL 2.0 after carful check for copyright holder --- threads.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 051903de..6cdbb0f7 100644 --- a/threads.c +++ b/threads.c @@ -5,24 +5,23 @@ * * File begun on 2007-12-14 by RGerhards * - * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007-2012 Adiscon GmbH. * * This file is part of rsyslog. * - * Rsyslog 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. - * - * Rsyslog 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 Rsyslog. If not, see . - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "config.h" -- cgit v1.2.3 From 1d7ba92156f5a5ac1783df563ec3344fdf8365df Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 May 2012 16:01:13 +0200 Subject: better debug instrumentation --> input thread names used for reporting --- threads.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 1aca6dbc..16de5631 100644 --- a/threads.c +++ b/threads.c @@ -31,12 +31,16 @@ #include #include #include +#if HAVE_SYS_PRCTL_H +# include +#endif #include "rsyslog.h" #include "dirty.h" #include "linkedlist.h" #include "threads.h" #include "srUtils.h" +#include "unicode-helper.h" /* linked list of currently-known threads */ static linkedList_t llThrds; @@ -77,6 +81,7 @@ static rsRetVal thrdDestruct(thrdInfo_t *pThis) } pthread_mutex_destroy(&pThis->mutThrd); pthread_cond_destroy(&pThis->condThrdTerm); + free(pThis->name); free(pThis); RETiRet; @@ -95,7 +100,8 @@ thrdTerminateNonCancel(thrdInfo_t *pThis) DEFiRet; assert(pThis != NULL); - DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID); + DBGPRINTF("request term via SIGTTIN for input thread '%s' 0x%x\n", + pThis->name, (unsigned) pThis->thrdID); pThis->bShallStop = TRUE; do { d_pthread_mutex_lock(&pThis->mutThrd); @@ -105,11 +111,11 @@ thrdTerminateNonCancel(thrdInfo_t *pThis) d_pthread_mutex_unlock(&pThis->mutThrd); if(Debug) { if(ret == ETIMEDOUT) { - dbgprintf("input thread term: timeout expired waiting on thread termination - canceling\n"); + dbgprintf("input thread term: timeout expired waiting on thread %s termination - canceling\n", pThis->name); pthread_cancel(pThis->thrdID); pThis->bIsActive = 0; } else if(ret == 0) { - dbgprintf("input thread term: thread returned normally and is terminated\n"); + dbgprintf("input thread term: thread %s returned normally and is terminated\n", pThis->name); } else { char errStr[1024]; int err = errno; @@ -119,7 +125,8 @@ thrdTerminateNonCancel(thrdInfo_t *pThis) } } } while(pThis->bIsActive); - DBGPRINTF("non-cancel input thread termination succeeded for thread 0x%x\n", (unsigned) pThis->thrdID); + DBGPRINTF("non-cancel input thread termination succeeded for thread %s 0x%x\n", + pThis->name, (unsigned) pThis->thrdID); RETiRet; } @@ -169,10 +176,23 @@ static void* thrdStarter(void *arg) { DEFiRet; thrdInfo_t *pThis = (thrdInfo_t*) arg; +# if HAVE_PRCTL && defined PR_SET_NAME + uchar thrdName[32] = "in:"; +# endif assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); +# if HAVE_PRCTL && defined PR_SET_NAME + /* set thread name - we ignore if the call fails, has no harsh consequences... */ + ustrncpy(thrdName+3, pThis->name, 20); + if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) { + DBGPRINTF("prctl failed, not setting thread name for '%s'\n", pThis->name); + } else { + DBGPRINTF("set thread name to '%s'\n", thrdName); + } +# endif + /* block all signals */ sigset_t sigSet; sigfillset(&sigSet); @@ -189,7 +209,8 @@ static void* thrdStarter(void *arg) */ iRet = pThis->pUsrThrdMain(pThis); - dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d, exiting now.\n", (unsigned long) pThis->thrdID, iRet); + dbgprintf("thrdStarter: usrThrdMain %s - 0x%lx returned with iRet %d, exiting now.\n", + pThis->name, (unsigned long) pThis->thrdID, iRet); /* signal master control that we exit (we do the mutex lock mostly to * keep the thread debugger happer, it would not really be necessary with @@ -208,7 +229,7 @@ static void* thrdStarter(void *arg) * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ -rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), sbool bNeedsCancel) +rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), sbool bNeedsCancel, uchar *name) { DEFiRet; thrdInfo_t *pThis; @@ -220,6 +241,7 @@ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdI pThis->pUsrThrdMain = thrdMain; pThis->pAfterRun = afterRun; pThis->bNeedsCancel = bNeedsCancel; + pThis->name = ustrdup(name); pthread_create(&pThis->thrdID, #ifdef HAVE_PTHREAD_SETSCHEDPARAM &default_thread_attr, -- cgit v1.2.3 From 9faf2240c4a8f09f3f6c2c9bbd47e48520524e03 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 22 Aug 2012 15:29:02 +0200 Subject: changed TRUE/FALSE to RSTRUE/RSFALSE This is done to prevent name claches with libraries. --- threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index 1aca6dbc..182b4789 100644 --- a/threads.c +++ b/threads.c @@ -96,7 +96,7 @@ thrdTerminateNonCancel(thrdInfo_t *pThis) assert(pThis != NULL); DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID); - pThis->bShallStop = TRUE; + pThis->bShallStop = RSTRUE; do { d_pthread_mutex_lock(&pThis->mutThrd); pthread_kill(pThis->thrdID, SIGTTIN); -- cgit v1.2.3 From 17d48fc49986af1e8e1cc2150213fe4f6111d7c6 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sun, 13 Jan 2013 12:14:58 +0100 Subject: added capability to output thread-id-to-function debug info This is a useful debug aid, but nothing of concern for regular users. --- threads.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index aea5de9f..e5006e90 100644 --- a/threads.c +++ b/threads.c @@ -183,9 +183,11 @@ static void* thrdStarter(void *arg) assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); + ustrncpy(thrdName+3, pThis->name, 20); + dbgOutputTID((char*)thrdName); + # if HAVE_PRCTL && defined PR_SET_NAME /* set thread name - we ignore if the call fails, has no harsh consequences... */ - ustrncpy(thrdName+3, pThis->name, 20); if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) { DBGPRINTF("prctl failed, not setting thread name for '%s'\n", pThis->name); } else { -- cgit v1.2.3 From 3e8ab2d389e802df8ec28b36ebe3f968e760b2db Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Fri, 22 Mar 2013 09:39:00 +0100 Subject: fix build on non-Linux systems --- threads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'threads.c') diff --git a/threads.c b/threads.c index e5006e90..990733a8 100644 --- a/threads.c +++ b/threads.c @@ -183,10 +183,10 @@ static void* thrdStarter(void *arg) assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); +# if HAVE_PRCTL && defined PR_SET_NAME ustrncpy(thrdName+3, pThis->name, 20); dbgOutputTID((char*)thrdName); -# if HAVE_PRCTL && defined PR_SET_NAME /* set thread name - we ignore if the call fails, has no harsh consequences... */ if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) { DBGPRINTF("prctl failed, not setting thread name for '%s'\n", pThis->name); -- cgit v1.2.3