2 * Bacula thread watchdog routine. General routine that monitors
3 * the daemon and signals a thread if it is blocked on a BSOCK
4 * too long. This prevents catastropic long waits -- generally
5 * due to Windows "hanging" the app.
7 * Kern Sibbald, January MMII
11 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of
16 the License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public
24 License along with this program; if not, write to the Free
25 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
33 /* Exported globals */
34 time_t watchdog_time; /* this has granularity of SLEEP_TIME */
37 #define TIMEOUT_SIGNAL SIGUSR2
38 #define SLEEP_TIME 30 /* examine things every 30 seconds */
40 /* Forward referenced functions */
41 static void *watchdog_thread(void *arg);
44 static pthread_mutex_t mutex;
45 static pthread_cond_t timer;
50 * Timeout signal comes here
52 static void timeout_handler(int sig)
54 return; /* thus interrupting the function */
59 * Initialize watchdog thread
61 * Returns: 0 on success
64 int init_watchdog(void)
68 struct sigaction sigtimer;
70 sigtimer.sa_flags = 0;
71 sigtimer.sa_handler = timeout_handler;
72 sigfillset(&sigtimer.sa_mask);
73 sigaction(TIMEOUT_SIGNAL, &sigtimer, NULL);
74 watchdog_time = time(NULL);
75 if ((stat = pthread_mutex_init(&mutex, NULL)) != 0) {
78 if ((stat = pthread_cond_init(&timer, NULL)) != 0) {
79 pthread_mutex_destroy(&mutex);
83 if ((stat = pthread_create(&wdid, NULL, watchdog_thread, (void *)NULL)) != 0) {
84 pthread_mutex_destroy(&mutex);
85 pthread_cond_destroy(&timer);
92 * Terminate the watchdog thread
94 * Returns: 0 on success
97 int term_watchdog(void)
101 if ((stat = pthread_mutex_lock(&mutex)) != 0) {
106 if ((stat = pthread_cond_signal(&timer)) != 0) {
107 pthread_mutex_unlock(&mutex);
110 if ((stat = pthread_mutex_unlock(&mutex)) != 0) {
118 * This is the actual watchdog thread.
120 static void *watchdog_thread(void *arg)
122 struct timespec timeout;
127 Dmsg0(200, "Start watchdog thread\n");
128 pthread_detach(pthread_self());
130 if ((stat = pthread_mutex_lock(&mutex)) != 0) {
138 Dmsg0(200, "Top of for loop\n");
140 watchdog_time = time(NULL); /* update timer */
142 /* Walk through all JCRs checking if any one is
143 * blocked for more than specified max time.
146 for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
147 free_locked_jcr(jcr);
148 if (jcr->JobId == 0) {
151 fd = jcr->store_bsock;
152 if (fd && fd->timer_start && (watchdog_time - fd->timer_start) > fd->timeout) {
153 fd->timed_out = TRUE;
154 Jmsg(jcr, M_ERROR, 0, "Watchdog sending kill to thread stalled reading Storage daemon.\n");
155 pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
157 fd = jcr->file_bsock;
158 if (fd && fd->timer_start && (watchdog_time - fd->timer_start) > fd->timeout) {
159 fd->timed_out = TRUE;
160 Jmsg(jcr, M_ERROR, 0, "Watchdog sending kill to thread stalled reading File daemon.\n");
161 pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
164 if (fd && fd->timer_start && (watchdog_time - fd->timer_start) > fd->timeout) {
165 fd->timed_out = TRUE;
166 Jmsg(jcr, M_ERROR, 0, "Watchdog sending kill to thread stalled reading Director.\n");
167 pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
173 gettimeofday(&tv, &tz);
175 timeout.tv_sec = tv.tv_sec + SLEEP_TIME;
177 Dmsg1(200, "pthread_cond_timedwait sec=%d\n", timeout.tv_sec);
178 #ifdef xxxxxxxxxxxxxxx_was_HAVE_CYGWIN
179 /* CYGWIN dies with a page fault the second
180 * time that pthread_cond_timedwait() is called
185 stat = pthread_cond_timedwait(&timer, &mutex, &timeout);
186 Dmsg1(200, "pthread_cond_timedwait stat=%d\n", stat);
189 } /* end of big for loop */
191 Dmsg0(200, "End watchdog\n");