]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/btimers.c
Mark translatable strings in all source files.
[bacula/bacula] / bacula / src / lib / btimers.c
1 /*
2  * Process and thread timer routines, built on top of watchdogs.
3  *
4  *    Nic Bellamy <nic@bellamy.co.nz>, October 2004.
5  *
6 */
7 /*
8    Copyright (C) 2004-2005 Kern Sibbald
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License
12    version 2 as amended with additional clauses defined in the
13    file LICENSE in the main source directory.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
18    the file LICENSE for additional details.
19
20  */
21
22 #include "bacula.h"
23 #include "jcr.h"
24
25 /* Forward referenced functions */
26 static void stop_btimer(btimer_t *wid);
27 static btimer_t *btimer_start_common(uint32_t wait);
28
29 /* Forward referenced callback functions */
30 static void callback_child_timer(watchdog_t *self);
31 static void callback_thread_timer(watchdog_t *self);
32 #ifdef xxx
33 static void destructor_thread_timer(watchdog_t *self);
34 static void destructor_child_timer(watchdog_t *self);
35 #endif
36
37 /*
38  * Start a timer on a child process of pid, kill it after wait seconds.
39  *
40  *  Returns: btimer_t *(pointer to btimer_t struct) on success
41  *           NULL on failure
42  */
43 btimer_t *start_child_timer(pid_t pid, uint32_t wait)
44 {
45    btimer_t *wid;
46
47    wid = btimer_start_common(wait);
48    if (wid == NULL) {
49       return NULL;
50    }
51    wid->type = TYPE_CHILD;
52    wid->pid = pid;
53    wid->killed = false;
54
55    wid->wd->callback = callback_child_timer;
56    wid->wd->one_shot = false;
57    wid->wd->interval = wait;
58    register_watchdog(wid->wd);
59
60    Dmsg3(900, "Start child timer %p, pid %d for %d secs.\n", wid, pid, wait);
61    return wid;
62 }
63
64 /*
65  * Stop child timer
66  */
67 void stop_child_timer(btimer_t *wid)
68 {
69    if (wid == NULL) {
70       Dmsg0(900, "stop_child_timer called with NULL btimer_id\n");
71       return;
72    }
73    Dmsg2(900, "Stop child timer %p pid %d\n", wid, wid->pid);
74    stop_btimer(wid);
75 }
76
77 #ifdef xxx
78 static void destructor_child_timer(watchdog_t *self)
79 {
80    btimer_t *wid = (btimer_t *)self->data;
81    free(wid->wd);
82    free(wid);
83 }
84 #endif
85
86 static void callback_child_timer(watchdog_t *self)
87 {
88    btimer_t *wid = (btimer_t *)self->data;
89
90    if (!wid->killed) {
91       /* First kill attempt; try killing it softly (kill -SONG) first */
92       wid->killed = true;
93
94       Dmsg2(050, "watchdog %p term PID %d\n", self, wid->pid);
95
96       /* Kill -TERM the specified PID, and reschedule a -KILL for 3 seconds
97        * later.
98        */
99       kill(wid->pid, SIGTERM);
100       self->interval = 3;
101    } else {
102       /* This is the second call - terminate with prejudice. */
103       Dmsg2(050, "watchdog %p kill PID %d\n", self, wid->pid);
104
105       kill(wid->pid, SIGKILL);
106
107       /* Setting one_shot to true before we leave ensures we don't get
108        * rescheduled.
109        */
110       self->one_shot = true;
111    }
112 }
113
114 /*
115  * Start a timer on a thread. kill it after wait seconds.
116  *
117  *  Returns: btimer_t *(pointer to btimer_t struct) on success
118  *           NULL on failure
119  */
120 btimer_t *start_thread_timer(pthread_t tid, uint32_t wait)
121 {
122    btimer_t *wid;
123    wid = btimer_start_common(wait);
124    if (wid == NULL) {
125       Dmsg1(900, "start_thread_timer return NULL from common. wait=%d.\n", wait);
126       return NULL;
127    }
128    wid->type = TYPE_PTHREAD;
129    wid->tid = tid;
130
131    wid->wd->callback = callback_thread_timer;
132    wid->wd->one_shot = true;
133    wid->wd->interval = wait;
134    register_watchdog(wid->wd);
135
136    Dmsg3(900, "Start thread timer %p tid %p for %d secs.\n", wid, tid, wait);
137
138    return wid;
139 }
140
141 /*
142  * Start a timer on a BSOCK. kill it after wait seconds.
143  *
144  *  Returns: btimer_t *(pointer to btimer_t struct) on success
145  *           NULL on failure
146  */
147 btimer_t *start_bsock_timer(BSOCK *bsock, uint32_t wait)
148 {
149    btimer_t *wid;
150    wid = btimer_start_common(wait);
151    if (wid == NULL) {
152       return NULL;
153    }
154    wid->type = TYPE_BSOCK;
155    wid->tid = pthread_self();
156    wid->bsock = bsock;
157
158    wid->wd->callback = callback_thread_timer;
159    wid->wd->one_shot = true;
160    wid->wd->interval = wait;
161    register_watchdog(wid->wd);
162
163    Dmsg4(950, "Start bsock timer %p tid=%p for %d secs at %d\n", wid,
164          wid->tid, wait, time(NULL));
165
166    return wid;
167 }
168
169 /*
170  * Stop bsock timer
171  */
172 void stop_bsock_timer(btimer_t *wid)
173 {
174    if (wid == NULL) {
175       Dmsg0(900, "stop_bsock_timer called with NULL btimer_id\n");
176       return;
177    }
178    Dmsg3(950, "Stop bsock timer %p tid=%p at %d.\n", wid, wid->tid, time(NULL));
179    stop_btimer(wid);
180 }
181
182
183 /*
184  * Stop thread timer
185  */
186 void stop_thread_timer(btimer_t *wid)
187 {
188    if (wid == NULL) {
189       Dmsg0(900, "stop_thread_timer called with NULL btimer_id\n");
190       return;
191    }
192    Dmsg2(900, "Stop thread timer %p tid=%p.\n", wid, wid->tid);
193    stop_btimer(wid);
194 }
195
196 #ifdef xxx
197 static void destructor_thread_timer(watchdog_t *self)
198 {
199    btimer_t *wid = (btimer_t *)self->data;
200    free(wid->wd);
201    free(wid);
202 }
203 #endif
204
205 static void callback_thread_timer(watchdog_t *self)
206 {
207    btimer_t *wid = (btimer_t *)self->data;
208
209    Dmsg4(50, "thread timer %p kill %s tid=%p at %d.\n", self,
210       wid->type == TYPE_BSOCK ? "bsock" : "thread", wid->tid, time(NULL));
211
212    if (wid->type == TYPE_BSOCK && wid->bsock) {
213       wid->bsock->timed_out = true;
214    }
215    pthread_kill(wid->tid, TIMEOUT_SIGNAL);
216 }
217
218 static btimer_t *btimer_start_common(uint32_t wait)
219 {
220    btimer_t *wid = (btimer_t *)malloc(sizeof(btimer_t));
221
222    wid->wd = new_watchdog();
223    if (wid->wd == NULL) {
224       free(wid);
225       return NULL;
226    }
227    wid->wd->data = wid;
228    wid->killed = FALSE;
229
230    return wid;
231 }
232
233 /*
234  * Stop btimer
235  */
236 static void stop_btimer(btimer_t *wid)
237 {
238    if (wid == NULL) {
239       Emsg0(M_ABORT, 0, _("stop_btimer called with NULL btimer_id\n"));
240    }
241    unregister_watchdog(wid->wd);
242    free(wid->wd);
243    free(wid);
244 }