6
6
* File begun on 2007-12-14 by RGerhards
8
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
8
* Copyright 2007, 2009 Rainer Gerhards and Adiscon GmbH.
10
10
* This file is part of rsyslog.
45
47
/* Construct a new thread object
47
static rsRetVal thrdConstruct(thrdInfo_t **ppThis)
50
thrdConstruct(thrdInfo_t **ppThis)
52
55
assert(ppThis != NULL);
54
if((pThis = calloc(1, sizeof(thrdInfo_t))) == NULL)
55
return RS_RET_OUT_OF_MEMORY;
57
/* OK, we got the element, now initialize members that should
60
pThis->mutTermOK = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
61
pthread_mutex_init (pThis->mutTermOK, NULL);
57
CHKmalloc(pThis = calloc(1, sizeof(thrdInfo_t)));
58
pthread_mutex_init(&pThis->mutThrd, NULL);
59
pthread_cond_init(&pThis->condThrdTerm, NULL);
77
76
if(pThis->bIsActive == 1) {
78
77
thrdTerminate(pThis);
80
free(pThis->mutTermOK);
79
pthread_mutex_destroy(&pThis->mutThrd);
80
pthread_cond_destroy(&pThis->condThrdTerm);
87
/* terminate a thread via the non-cancel interface
88
* This is a separate function as it involves a bit more of code.
89
* rgerhads, 2009-10-15
91
static inline rsRetVal
92
thrdTerminateNonCancel(thrdInfo_t *pThis)
94
struct timespec tTimeout;
97
assert(pThis != NULL);
99
DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID);
100
pThis->bShallStop = TRUE;
102
d_pthread_mutex_lock(&pThis->mutThrd);
103
pthread_kill(pThis->thrdID, SIGTTIN);
104
timeoutComp(&tTimeout, 10); /* a fixed 10ms timeout, do after lock (may take long!) */
105
ret = d_pthread_cond_timedwait(&pThis->condThrdTerm, &pThis->mutThrd, &tTimeout);
106
d_pthread_mutex_unlock(&pThis->mutThrd);
108
if(ret == ETIMEDOUT) {
109
dbgprintf("input thread term: had a timeout waiting on thread termination\n");
110
} else if(ret == 0) {
111
dbgprintf("input thread term: thread returned normally and is terminated\n");
115
rs_strerror_r(err, errStr, sizeof(errStr));
116
dbgprintf("input thread term: cond_wait returned with error %d: %s\n",
120
} while(pThis->bIsActive);
121
DBGPRINTF("non-cancel input thread termination succeeded for thread 0x%x\n", (unsigned) pThis->thrdID);
87
127
/* terminate a thread gracefully.
89
129
rsRetVal thrdTerminate(thrdInfo_t *pThis)
92
132
assert(pThis != NULL);
94
pthread_cancel(pThis->thrdID);
95
pthread_join(pThis->thrdID, NULL); /* wait for cancel to complete */
134
if(pThis->bNeedsCancel) {
135
DBGPRINTF("request term via canceling for input thread 0x%x\n", (unsigned) pThis->thrdID);
136
pthread_cancel(pThis->thrdID);
137
pThis->bIsActive = 0;
139
thrdTerminateNonCancel(pThis);
141
pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */
98
143
/* call cleanup function, if any */
99
144
if(pThis->pAfterRun != NULL)
132
177
sigfillset(&sigSet);
133
178
pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
180
/* but ignore SIGTTN, which we (ab)use to signal the thread to shutdown -- rgerhards, 2009-07-20 */
181
sigemptyset(&sigSet);
182
sigaddset(&sigSet, SIGTTIN);
183
pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL);
135
185
/* setup complete, we are now ready to execute the user code. We will not
136
186
* regain control until the user code is finished, in which case we terminate
139
189
iRet = pThis->pUsrThrdMain(pThis);
141
191
dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d, exiting now.\n", (unsigned long) pThis->thrdID, iRet);
193
/* signal master control that we exit (we do the mutex lock mostly to
194
* keep the thread debugger happer, it would not really be necessary with
195
* the logic we employ...)
197
pThis->bIsActive = 0;
198
d_pthread_mutex_lock(&pThis->mutThrd);
199
pthread_cond_signal(&pThis->condThrdTerm);
200
d_pthread_mutex_unlock(&pThis->mutThrd);
147
207
* executing threads. It is added at the end of the list.
148
208
* rgerhards, 2007-12-14
150
rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *))
210
rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), sbool bNeedsCancel)
153
213
thrdInfo_t *pThis;
159
219
pThis->bIsActive = 1;
160
220
pThis->pUsrThrdMain = thrdMain;
161
221
pThis->pAfterRun = afterRun;
222
pThis->bNeedsCancel = bNeedsCancel;
162
223
i = pthread_create(&pThis->thrdID, NULL, thrdStarter, pThis);
163
224
CHKiRet(llAppend(&llThrds, NULL, pThis));
184
245
rsRetVal thrdExit(void)
188
248
iRet = llDestroy(&llThrds);
194
/* thrdSleep() - a fairly portable way to put a thread to sleep. It
196
* a) the wake-time is over
197
* b) the thread shall be terminated
198
* Returns RS_RET_OK if all went well, RS_RET_TERMINATE_NOW if the calling
199
* thread shall be terminated and any other state if an error happened.
200
* rgerhards, 2007-12-17
203
thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds)
206
struct timeval tvSelectTimeout;
208
assert(pThis != NULL);
209
tvSelectTimeout.tv_sec = iSeconds;
210
tvSelectTimeout.tv_usec = iuSeconds; /* micro seconds */
211
select(1, NULL, NULL, NULL, &tvSelectTimeout);
212
if(pThis->bShallStop)
213
iRet = RS_RET_TERMINATE_NOW;