source: roaraudio/libroar/watchdog.c @ 5823:f9f70dbaa376

Last change on this file since 5823:f9f70dbaa376 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

File size: 5.6 KB
Line 
1//watchdog.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-2013
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#define _CONF_DEFAULT ROAR_WATCHDOG_CONF_STOPPABLE|ROAR_WATCHDOG_CONF_CLOCK_INTERNAL;
39static int _config = _CONF_DEFAULT;
40static int _triggered = 0;
41static int _running = 0;
42static int_least32_t _timeout = 10000; // 10 sec.
43static int (*_callback)(enum roar_watchdog_event event) = NULL;
44static pid_t _starter_pid = 0;
45
46#ifdef ROAR_HAVE_ALARM
47static void _on_sig_alarm (int signum) {
48 (void)signum;
49 signal(SIGALRM,  _on_sig_alarm);
50 alarm(_timeout/1000);
51 roar_watchdog_tick();
52}
53#endif
54
55static int __event_handler(enum roar_watchdog_event event) {
56 int ret;
57
58 if ( event == ROAR_WATCHDOG_DOUBLETIMEOUT ) {
59  ROAR_ERR("Watchdog event: DoubleTimeOut. Bad. Terminating program.");
60  // panic...
61  roar_panic(ROAR_FATAL_ERROR_WATCHDOG, NULL);
62 } else if ( event == ROAR_WATCHDOG_TIMEOUT ) {
63  ROAR_ERR("Watchdog event: TimeOut. Cleaning Up.");
64 }
65
66 if ( _callback != NULL ) {
67  if ( (_config & ROAR_WATCHDOG_CONF_EVENTS_ALSO_MINOR) ||
68       event == ROAR_WATCHDOG_TIMEOUT                   ||
69       event == ROAR_WATCHDOG_START                     ||
70       event == ROAR_WATCHDOG_STOP ) {
71   ret = _callback(event);
72   if ( ret == -1 && event == ROAR_WATCHDOG_TIMEOUT )
73    __event_handler(ROAR_WATCHDOG_DOUBLETIMEOUT);
74  }
75 }
76
77 if ( event == ROAR_WATCHDOG_TIMEOUT ) {
78  ROAR_ERR("Watchdog event: TimeOut. Terminating program.");
79  roar_panic(ROAR_FATAL_ERROR_WATCHDOG, NULL);
80 }
81
82 return 0;
83}
84
85// start the watchdog.
86// timeout is in ms.
87int roar_watchdog_start(int config, int_least32_t timeout, int (*callback)(enum roar_watchdog_event event)) {
88 int ret = -1;
89
90 if ( config == ROAR_WATCHDOG_CONF_DEFAULTS ) {
91  config = _CONF_DEFAULT;
92 } else if ( config == ROAR_WATCHDOG_CONF_RESTART ) {
93  config = _config;
94  if ( timeout == -1 )
95   timeout = _timeout;
96  if ( callback == NULL )
97   callback = _callback;
98 }
99
100 if ( timeout < 1 ) {
101  roar_err_set(ROAR_ERROR_CAUSALITY);
102  return -1;
103 }
104
105 if ( _running ) {
106  if ( _config & ROAR_WATCHDOG_CONF_STOPPABLE ) {
107   if ( roar_watchdog_stop() == -1 )
108    return -1;
109  } else {
110   roar_err_set(ROAR_ERROR_BUSY);
111   return -1;
112  }
113 }
114
115 if ( !(config & ROAR_WATCHDOG_CONF_CLOCK_EXTERNAL) ) {
116#ifdef ROAR_HAVE_ALARM
117  if ( config & ROAR_WATCHDOG_CONF_CLOCK_ROUND_UP ) {
118   if ( timeout % 1000 )
119    timeout += 1000;
120  }
121
122  timeout /= 1000;
123  if ( timeout == 0 )
124   timeout = 1;
125
126  timeout *= 1000;
127#else
128  roar_err_set(ROAR_ERROR_NOSYS);
129  return -1;
130#endif
131 }
132
133 _config   = config;
134 _timeout  = timeout;
135 _callback = callback;
136
137 if ( config & ROAR_WATCHDOG_CONF_CLOCK_EXTERNAL ) {
138  ret = __event_handler(ROAR_WATCHDOG_START);
139#ifdef ROAR_HAVE_ALARM
140 } else {
141  signal(SIGALRM,  _on_sig_alarm);
142  alarm(_timeout/1000);
143  ret = 0;
144#endif
145 }
146
147 if ( ret == -1 )
148  return -1;
149
150 _running = 1;
151 _starter_pid = getpid();
152 return 0;
153}
154
155// Get timeout for watchdog.
156// This may be diffrent from the requested time.
157int_least32_t roar_watchdog_gettime(void) {
158 if ( !_running ) {
159  roar_err_set(ROAR_ERROR_NOENT);
160  return -1;
161 }
162 return _timeout;
163}
164
165// stop it, if stopping is enabled.
166int roar_watchdog_stop(void) {
167 int ret;
168
169 if ( !_running )
170  return 0;
171
172 // test if we are allowed to stop the watchdog.
173 // In addition always allow to stop it in childs.
174 if ( !(_config & ROAR_WATCHDOG_CONF_STOPPABLE) && _starter_pid == getpid() ) {
175  ROAR_WARN("roar_watchdog_stop(void): Software tries to stop watchdog but is not allowed to.");
176  roar_err_set(ROAR_ERROR_PERM);
177  return -1;
178 }
179
180
181#ifdef ROAR_HAVE_ALARM
182 if ( !(_config & ROAR_WATCHDOG_CONF_CLOCK_EXTERNAL) ) {
183  alarm(0);
184  _running = 0;
185 }
186#endif
187
188 ret = __event_handler(ROAR_WATCHDOG_STOP);
189 if ( ret != -1 )
190  _running = 0;
191
192 return ret;
193}
194
195// Trigger the watchdog to show that we are still alive.
196int roar_watchdog_trigger(void) {
197 if ( !_running )
198  return 0;
199
200 _triggered = 1;
201 return __event_handler(ROAR_WATCHDOG_TRIGGER);
202}
203
204// Trigger the watchdog clock. This is only used if configured to run with external clock source.
205int roar_watchdog_tick(void) {
206 int ret = 0;
207
208 ROAR_DBG("roar_watchdog_tick(void) = ?");
209
210 if ( !_running )
211  return 0;
212
213 if ( _triggered == 0 ) {
214  _triggered = -1;
215  ret = __event_handler(ROAR_WATCHDOG_TIMEOUT);
216 } else if ( _triggered == -1 ) {
217  ret = __event_handler(ROAR_WATCHDOG_DOUBLETIMEOUT);
218 } else {
219  _triggered = 0;
220 }
221
222 return ret;
223}
224
225//ll
Note: See TracBrowser for help on using the repository browser.