~ubuntu-branches/ubuntu/utopic/rsyslog/utopic

« back to all changes in this revision

Viewing changes to threads.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2010-10-20 01:48:39 UTC
  • mfrom: (1.1.18 upstream)
  • mto: (16.1.9 sid)
  • mto: This revision was merged to the branch mainline in revision 37.
  • Revision ID: james.westby@ubuntu.com-20101020014839-mnggukpri3guor0q
Tags: 5.7.1-1
* New upstream development release.
* debian/rsyslog.install
  - Install omruleset.so plugin: http://www.rsyslog.com/doc/omruleset.html
* debian/rsyslog.default
  - Start rsyslogd with native -c5 mode.
* Install systemd unit files which allow to run rsyslog in socket activation
  mode when systemd is used.
* debian/patches/02-install_also_rsyslog_socket.patch
  - When enabling rsyslog.service also enable rsyslog.socket. Patch
    cherry-picked from upstream Git.
* Bump debhelper compatibility level to 8. Update Build-Depends accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * 
6
6
 * File begun on 2007-12-14 by RGerhards
7
7
 *
8
 
 * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
 
8
 * Copyright 2007, 2009 Rainer Gerhards and Adiscon GmbH.
9
9
 *
10
10
 * This file is part of rsyslog.
11
11
 *
29
29
#include <stdlib.h>
30
30
#include <string.h>
31
31
#include <signal.h>
 
32
#include <errno.h>
32
33
#include <pthread.h>
33
34
#include <assert.h>
34
35
 
36
37
#include "dirty.h"
37
38
#include "linkedlist.h"
38
39
#include "threads.h"
 
40
#include "srUtils.h"
39
41
 
40
42
/* linked list of currently-known threads */
41
43
static linkedList_t llThrds;
44
46
 
45
47
/* Construct a new thread object
46
48
 */
47
 
static rsRetVal thrdConstruct(thrdInfo_t **ppThis)
 
49
static rsRetVal
 
50
thrdConstruct(thrdInfo_t **ppThis)
48
51
{
49
52
        DEFiRet;
50
53
        thrdInfo_t *pThis;
51
54
 
52
55
        assert(ppThis != NULL);
53
56
 
54
 
        if((pThis = calloc(1, sizeof(thrdInfo_t))) == NULL)
55
 
                return RS_RET_OUT_OF_MEMORY;
56
 
 
57
 
        /* OK, we got the element, now initialize members that should
58
 
         * not be zero-filled.
59
 
         */
60
 
        pThis->mutTermOK = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
61
 
        pthread_mutex_init (pThis->mutTermOK, NULL);
62
 
 
 
57
        CHKmalloc(pThis = calloc(1, sizeof(thrdInfo_t)));
 
58
        pthread_mutex_init(&pThis->mutThrd, NULL);
 
59
        pthread_cond_init(&pThis->condThrdTerm, NULL);
63
60
        *ppThis = pThis;
 
61
 
 
62
finalize_it:
64
63
        RETiRet;
65
64
}
66
65
 
77
76
        if(pThis->bIsActive == 1) {
78
77
                thrdTerminate(pThis);
79
78
        }
80
 
        free(pThis->mutTermOK);
 
79
        pthread_mutex_destroy(&pThis->mutThrd);
 
80
        pthread_cond_destroy(&pThis->condThrdTerm);
81
81
        free(pThis);
82
82
 
83
83
        RETiRet;
84
84
}
85
85
 
86
86
 
 
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
 
90
 */
 
91
static inline rsRetVal
 
92
thrdTerminateNonCancel(thrdInfo_t *pThis)
 
93
{
 
94
        struct timespec tTimeout;
 
95
        int ret;
 
96
        DEFiRet;
 
97
        assert(pThis != NULL);
 
98
 
 
99
        DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID);
 
100
        pThis->bShallStop = TRUE;
 
101
        do {
 
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);
 
107
                if(Debug) {
 
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");
 
112
                        } else {
 
113
                                char errStr[1024];
 
114
                                int err = errno;
 
115
                                rs_strerror_r(err, errStr, sizeof(errStr));
 
116
                                dbgprintf("input thread term: cond_wait returned with error %d: %s\n",
 
117
                                          err, errStr);
 
118
                        }
 
119
                }
 
120
        } while(pThis->bIsActive);
 
121
        DBGPRINTF("non-cancel input thread termination succeeded for thread 0x%x\n", (unsigned) pThis->thrdID);
 
122
 
 
123
        RETiRet;
 
124
}
 
125
 
 
126
 
87
127
/* terminate a thread gracefully.
88
128
 */
89
129
rsRetVal thrdTerminate(thrdInfo_t *pThis)
91
131
        DEFiRet;
92
132
        assert(pThis != NULL);
93
133
        
94
 
        pthread_cancel(pThis->thrdID);
95
 
        pthread_join(pThis->thrdID, NULL); /* wait for cancel to complete */
96
 
        pThis->bIsActive = 0;
 
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;
 
138
        } else {
 
139
                thrdTerminateNonCancel(pThis);
 
140
        }
 
141
        pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */
97
142
 
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);
134
179
 
 
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);
 
184
 
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
137
187
         * the thread.
139
189
        iRet = pThis->pUsrThrdMain(pThis);
140
190
 
141
191
        dbgprintf("thrdStarter: usrThrdMain 0x%lx returned with iRet %d, exiting now.\n", (unsigned long) pThis->thrdID, iRet);
 
192
 
 
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...)
 
196
         */
 
197
        pThis->bIsActive = 0;
 
198
        d_pthread_mutex_lock(&pThis->mutThrd);
 
199
        pthread_cond_signal(&pThis->condThrdTerm);
 
200
        d_pthread_mutex_unlock(&pThis->mutThrd);
 
201
 
142
202
        ENDfunc
143
203
        pthread_exit(0);
144
204
}
147
207
 * executing threads. It is added at the end of the list.
148
208
 * rgerhards, 2007-12-14
149
209
 */
150
 
rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *))
 
210
rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), sbool bNeedsCancel)
151
211
{
152
212
        DEFiRet;
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));
164
225
 
184
245
rsRetVal thrdExit(void)
185
246
{
186
247
        DEFiRet;
187
 
 
188
248
        iRet = llDestroy(&llThrds);
189
 
 
190
 
        RETiRet;
191
 
}
192
 
 
193
 
 
194
 
/* thrdSleep() - a fairly portable way to put a thread to sleep. It 
195
 
 * will wake up when
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
201
 
 */
202
 
rsRetVal
203
 
thrdSleep(thrdInfo_t *pThis, int iSeconds, int iuSeconds)
204
 
{
205
 
        DEFiRet;
206
 
        struct timeval tvSelectTimeout;
207
 
 
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;
214
 
        RETiRet;
215
 
}
216
 
 
217
 
 
218
 
/*
219
 
 * vi:set ai:
 
249
        RETiRet;
 
250
}
 
251
 
 
252
 
 
253
/* vi:set ai:
220
254
 */