2 * Process and thread timer routines, built on top of watchdogs.
4 * Nic Bellamy <nic@bellamy.co.nz>, October 2004.
8 Copyright (C) 2000-2004 Kern Sibbald and John Walker
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.
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.
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,
30 /* Forward referenced functions */
31 static void stop_btimer(btimer_t *wid);
32 static btimer_t *btimer_start_common(uint32_t wait);
34 /* Forward referenced callback functions */
35 static void callback_child_timer(watchdog_t *self);
36 static void callback_thread_timer(watchdog_t *self);
38 static void destructor_thread_timer(watchdog_t *self);
39 static void destructor_child_timer(watchdog_t *self);
43 * Start a timer on a child process of pid, kill it after wait seconds.
45 * Returns: btimer_t *(pointer to btimer_t struct) on success
48 btimer_t *start_child_timer(pid_t pid, uint32_t wait)
52 wid = btimer_start_common(wait);
56 wid->type = TYPE_CHILD;
60 wid->wd->callback = callback_child_timer;
61 wid->wd->one_shot = false;
62 wid->wd->interval = wait;
63 register_watchdog(wid->wd);
65 Dmsg3(200, "Start child timer %p, pid %d for %d secs.\n", wid, pid, wait);
72 void stop_child_timer(btimer_t *wid)
75 Dmsg0(200, "stop_child_timer called with NULL btimer_id\n");
78 Dmsg2(200, "Stop child timer %p pid %d\n", wid, wid->pid);
83 static void destructor_child_timer(watchdog_t *self)
85 btimer_t *wid = (btimer_t *)self->data;
91 static void callback_child_timer(watchdog_t *self)
93 btimer_t *wid = (btimer_t *)self->data;
96 /* First kill attempt; try killing it softly (kill -SONG) first */
99 Dmsg2(200, "watchdog %p term PID %d\n", self, wid->pid);
101 /* Kill -TERM the specified PID, and reschedule a -KILL for 3 seconds
104 kill(wid->pid, SIGTERM);
107 /* This is the second call - terminate with prejudice. */
108 Dmsg2(200, "watchdog %p kill PID %d\n", self, wid->pid);
110 kill(wid->pid, SIGKILL);
112 /* Setting one_shot to true before we leave ensures we don't get
115 self->one_shot = true;
120 * Start a timer on a thread. kill it after wait seconds.
122 * Returns: btimer_t *(pointer to btimer_t struct) on success
125 btimer_t *start_thread_timer(pthread_t tid, uint32_t wait)
128 wid = btimer_start_common(wait);
130 Dmsg1(200, "start_thread_timer return NULL from common. wait=%d.\n", wait);
133 wid->type = TYPE_PTHREAD;
136 wid->wd->callback = callback_thread_timer;
137 wid->wd->one_shot = true;
138 wid->wd->interval = wait;
139 register_watchdog(wid->wd);
141 Dmsg3(200, "Start thread timer %p tid %p for %d secs.\n", wid, tid, wait);
147 * Start a timer on a BSOCK. kill it after wait seconds.
149 * Returns: btimer_t *(pointer to btimer_t struct) on success
152 btimer_t *start_bsock_timer(BSOCK *bsock, uint32_t wait)
155 wid = btimer_start_common(wait);
159 wid->type = TYPE_BSOCK;
160 wid->tid = pthread_self();
163 wid->wd->callback = callback_thread_timer;
164 wid->wd->one_shot = true;
165 wid->wd->interval = wait;
166 register_watchdog(wid->wd);
168 Dmsg3(50, "Start bsock timer %p tip %p for %d secs.\n", wid, wid->tid, wait);
176 void stop_bsock_timer(btimer_t *wid)
179 Dmsg0(200, "stop_bsock_timer called with NULL btimer_id\n");
182 Dmsg2(50, "Stop bsock timer %p tid %p.\n", wid, wid->tid);
190 void stop_thread_timer(btimer_t *wid)
193 Dmsg0(200, "stop_thread_timer called with NULL btimer_id\n");
196 Dmsg2(200, "Stop thread timer %p tid %p.\n", wid, wid->tid);
201 static void destructor_thread_timer(watchdog_t *self)
203 btimer_t *wid = (btimer_t *)self->data;
209 static void callback_thread_timer(watchdog_t *self)
211 btimer_t *wid = (btimer_t *)self->data;
213 Dmsg2(50, "watchdog %p kill thread %d\n", self, wid->tid);
215 if (wid->type == TYPE_BSOCK && wid->bsock) {
216 Dmsg0(50, "kill type bsock ...\n");
217 wid->bsock->timed_out = true;
219 pthread_kill(wid->tid, TIMEOUT_SIGNAL);
222 static btimer_t *btimer_start_common(uint32_t wait)
224 btimer_t *wid = (btimer_t *)malloc(sizeof(btimer_t));
226 wid->wd = new_watchdog();
227 if (wid->wd == NULL) {
240 static void stop_btimer(btimer_t *wid)
243 Emsg0(M_ABORT, 0, "stop_btimer called with NULL btimer_id\n");
245 unregister_watchdog(wid->wd);