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