]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/btimers.c
Misc see kes-1.34
[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) 2000-2004 Kern Sibbald and John Walker
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 as
12    published by the Free Software Foundation; either version 2 of
13    the License, or (at your option) any later version.
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 GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public
21    License along with this program; if not, write to the Free
22    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23    MA 02111-1307, USA.
24
25  */
26
27 #include "bacula.h"
28 #include "jcr.h"
29
30 /* Forward referenced functions */
31 static void stop_btimer(btimer_t *wid);
32 static btimer_t *btimer_start_common(uint32_t wait);
33
34 /* Forward referenced callback functions */
35 static void callback_child_timer(watchdog_t *self);
36 static void callback_thread_timer(watchdog_t *self);
37 #ifdef xxx
38 static void destructor_thread_timer(watchdog_t *self);
39 static void destructor_child_timer(watchdog_t *self);
40 #endif
41
42 /* 
43  * Start a timer on a child process of pid, kill it after wait seconds.
44  *
45  *  Returns: btimer_t *(pointer to btimer_t struct) on success
46  *           NULL on failure
47  */
48 btimer_t *start_child_timer(pid_t pid, uint32_t wait)
49 {
50    btimer_t *wid;
51
52    wid = btimer_start_common(wait);
53    if (wid == NULL) {
54       return NULL;
55    }
56    wid->type = TYPE_CHILD;
57    wid->pid = pid;
58    wid->killed = false;
59
60    wid->wd->callback = callback_child_timer;
61    wid->wd->one_shot = false;
62    wid->wd->interval = wait;
63    register_watchdog(wid->wd);
64
65    Dmsg3(200, "Start child timer %p, pid %d for %d secs.\n", wid, pid, wait);
66    return wid;
67 }
68
69 /*
70  * Stop child timer
71  */
72 void stop_child_timer(btimer_t *wid)
73 {
74    if (wid == NULL) {
75       Dmsg0(200, "stop_child_timer called with NULL btimer_id\n");
76       return;
77    }
78    Dmsg2(200, "Stop child timer %p pid %d\n", wid, wid->pid);
79    stop_btimer(wid);
80 }
81
82 #ifdef xxx
83 static void destructor_child_timer(watchdog_t *self)
84 {
85    btimer_t *wid = (btimer_t *)self->data;
86    free(wid->wd);
87    free(wid);
88 }
89 #endif
90
91 static void callback_child_timer(watchdog_t *self)
92 {
93    btimer_t *wid = (btimer_t *)self->data;
94
95    if (!wid->killed) {
96       /* First kill attempt; try killing it softly (kill -SONG) first */
97       wid->killed = true;
98
99       Dmsg2(200, "watchdog %p term PID %d\n", self, wid->pid);
100
101       /* Kill -TERM the specified PID, and reschedule a -KILL for 3 seconds
102        * later.
103        */
104       kill(wid->pid, SIGTERM);
105       self->interval = 3;
106    } else {
107       /* This is the second call - terminate with prejudice. */
108       Dmsg2(200, "watchdog %p kill PID %d\n", self, wid->pid);
109
110       kill(wid->pid, SIGKILL);
111
112       /* Setting one_shot to true before we leave ensures we don't get
113        * rescheduled.
114        */
115       self->one_shot = true;
116    }
117 }
118
119 /* 
120  * Start a timer on a thread. kill it after wait seconds.
121  *
122  *  Returns: btimer_t *(pointer to btimer_t struct) on success
123  *           NULL on failure
124  */
125 btimer_t *start_thread_timer(pthread_t tid, uint32_t wait)
126 {
127    btimer_t *wid;
128    wid = btimer_start_common(wait);
129    if (wid == NULL) {
130       return NULL;
131    }
132    wid->type = TYPE_PTHREAD;
133    wid->tid = tid;
134
135    wid->wd->callback = callback_thread_timer;
136    wid->wd->one_shot = true;
137    wid->wd->interval = wait;
138    register_watchdog(wid->wd);
139
140    Dmsg3(200, "Start thread timer %p tid %p for %d secs.\n", wid, tid, wait);
141
142    return wid;
143 }
144
145 /* 
146  * Start a timer on a BSOCK. kill it after wait seconds.
147  *
148  *  Returns: btimer_t *(pointer to btimer_t struct) on success
149  *           NULL on failure
150  */
151 btimer_t *start_bsock_timer(BSOCK *bsock, uint32_t wait)
152 {
153    btimer_t *wid;
154    wid = btimer_start_common(wait);
155    if (wid == NULL) {
156       return NULL;
157    }
158    wid->type = TYPE_BSOCK;
159    wid->tid = pthread_self();
160    wid->bsock = bsock;
161
162    wid->wd->callback = callback_thread_timer;
163    wid->wd->one_shot = true;
164    wid->wd->interval = wait;
165    register_watchdog(wid->wd);
166
167    Dmsg3(200, "Start thread timer %p tip %p for %d secs.\n", wid, wid->tid, wait);
168
169    return wid;
170 }
171
172 /*
173  * Stop bsock timer
174  */
175 void stop_bsock_timer(btimer_t *wid)
176 {
177    if (wid == NULL) {
178       Dmsg0(200, "stop_bsock_timer called with NULL btimer_id\n");
179       return;
180    }
181    Dmsg2(200, "Stop bsock timer %p tid %p.\n", wid, wid->tid);
182    stop_btimer(wid);
183 }
184
185
186 /*
187  * Stop thread timer
188  */
189 void stop_thread_timer(btimer_t *wid)
190 {
191    if (wid == NULL) {
192       Dmsg0(200, "stop_thread_timer called with NULL btimer_id\n");
193       return;
194    }
195    Dmsg2(200, "Stop thread timer %p tid %p.\n", wid, wid->tid);
196    stop_btimer(wid);
197 }
198
199 #ifdef xxx
200 static void destructor_thread_timer(watchdog_t *self)
201 {
202    btimer_t *wid = (btimer_t *)self->data;
203    free(wid->wd);
204    free(wid);
205 }
206 #endif
207
208 static void callback_thread_timer(watchdog_t *self)
209 {
210    btimer_t *wid = (btimer_t *)self->data;
211
212    Dmsg2(200, "watchdog %p kill thread %d\n", self, wid->tid);
213
214    if (wid->type == TYPE_BSOCK && wid->bsock) {
215       Dmsg0(200, "kill type bsock ...\n");
216       wid->bsock->timed_out = true;
217    }
218    pthread_kill(wid->tid, TIMEOUT_SIGNAL);
219 }
220
221 static btimer_t *btimer_start_common(uint32_t wait)
222 {
223    btimer_t *wid = (btimer_t *)malloc(sizeof(btimer_t));
224
225    wid->wd = new_watchdog();
226    if (wid->wd == NULL) {
227       free(wid);
228       return NULL;
229    }
230    wid->wd->data = wid;
231    wid->killed = FALSE;
232
233    return wid;
234 }
235
236 /*
237  * Stop btimer
238  */
239 static void stop_btimer(btimer_t *wid)
240 {
241    if (wid == NULL) {
242       Emsg0(M_ABORT, 0, "stop_btimer called with NULL btimer_id\n");
243    }
244    unregister_watchdog(wid->wd);
245    free(wid->wd);
246    free(wid);
247 }