summaryrefslogtreecommitdiffstats
path: root/threads.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2007-12-20 08:54:51 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2007-12-20 08:54:51 +0000
commit2eb19201b3f4be01057c1b958a077b5fb2fce107 (patch)
tree067b64859e42ff5ad903f20ec9c22bd3600eabe6 /threads.c
parent02a46ee6b0b7f326dc0affd2caae961e09bf9a3b (diff)
downloadrsyslog-2eb19201b3f4be01057c1b958a077b5fb2fce107.tar.gz
rsyslog-2eb19201b3f4be01057c1b958a077b5fb2fce107.tar.xz
rsyslog-2eb19201b3f4be01057c1b958a077b5fb2fce107.zip
- 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.
Diffstat (limited to 'threads.c')
-rw-r--r--threads.c33
1 files changed, 27 insertions, 6 deletions
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 <stdlib.h>
#include <string.h>
@@ -33,6 +36,7 @@
#include <pthread.h>
#include <assert.h>
+#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;
}