Move signal processing completly out of the signal handler (including logging)
[bpdyndnsd] / src / main.cpp
CommitLineData
b1be615b
BS
1/** @file
2 * @brief The main function.
3 *
4 *
5 *
6 * @copyright Intra2net AG
7 * @license GPLv2
8*/
4545a371
BS
9
10#ifdef HAVE_CONFIG_H
11#include <config.h>
12#endif
13
c47386eb 14#define PIDFILE "/var/run/bpdyndnsd/bpdyndnsd.pid"
388f4ab0 15
4545a371 16#include <iostream>
88a594e8 17#include <fstream>
4545a371
BS
18#include <list>
19#include <string>
4545a371 20#include <boost/foreach.hpp>
88a594e8
BS
21#include <sys/types.h>
22#include <signal.h>
23
4de6a9b8 24#include "updater.hpp"
4545a371 25
4545a371
BS
26using namespace std;
27
88a594e8 28Updater::Ptr updater;
4f4a6039 29volatile bool need_config_reload = false;
c5a6b1fe 30volatile bool exit_now = false;
c5675c01 31
a6aac246
TJ
32volatile bool caught_sig_usr1 = false;
33volatile bool caught_sig_usr2 = false;
34volatile bool caught_sig_rtmin1 = false;
35
4545a371 36/**
388f4ab0
BS
37 * Checks if a bpdyndnsd process is already running.
38 * @param updater Shared Pointer to updater, needed for logging.
39 * @return 0 if process not running already or pid of already running process.
40 */
c5675c01 41int check_for_running_process()
388f4ab0
BS
42{
43 ifstream pidfile(PIDFILE);
44 if ( pidfile.is_open() )
45 {
46 int pid;
47 pidfile >> pid;
48 if ( pid > 0 )
49 updater->get_logger()->print_pid_found(pid);
50 else
51 return 0;
52
53 // check if process still running ret_val==-1 -> not runnig, ret_val==0 -> running
54 if ( kill(pid,0) == 0)
55 {
56 updater->get_logger()->print_process_already_running(pid);
57 pidfile.close();
58 return pid;
59 }
60 }
61 pidfile.close();
62 return 0;
63}
64
c5675c01
BS
65
66/**
67 * Writes the pid into the pidfile.
68 * @param pid The process's pid.
69 */
667c672c 70int write_pidfile(int pid)
388f4ab0
BS
71{
72 ofstream pidfile(PIDFILE);
73 if ( pidfile.is_open() )
74 {
75 pidfile << pid << endl;
76 }
667c672c
BS
77 else
78 {
79 updater->get_logger()->print_error_opening_rw(PIDFILE);
80 return -1;
81 }
388f4ab0 82 pidfile.close();
667c672c 83 return 0;
388f4ab0
BS
84}
85
c5675c01
BS
86
87/**
e304c27b
BS
88 * Parent shutdown function
89 * @return 0 if all is fine, -1 otherwise
90 */
91int shutdown_parent(bool remove_pid, int ret_val)
92{
93 // starting shutdown_parent
94 updater->get_logger()->print_starting_shutdown_parent();
95
96 // remove pidfile if requested
97 if(remove_pid)
98 unlink(PIDFILE);
99
100 // shutdown parent complete
101 updater->get_logger()->print_shutdown_parent_succeeded();
102
103 // release shared pointer
104 updater.reset();
105
106 exit(ret_val);
107}
108
109
110/**
111 * Shutdown function
112 * @return 0 if all is fine, -1 otherwise
113 */
114int shutdown()
115{
116 int ret_val = 0;
117
118 // starting shutdown
119 updater->get_logger()->print_starting_shutdown();
120
121 // serialize actual service objects
122 if ( updater->get_service_holder()->serialize_services() != 0 )
123 ret_val = -1;
124
125 // unlink pidfile
126 unlink(PIDFILE);
127
128 // shutdown complete
129 updater->get_logger()->print_shutdown_succeeded();
130
131 // release shared pointer
132 updater.reset();
133
134 return ret_val;
135}
136
137
138/**
c5675c01
BS
139 * Signal SIGTERM caught, releasing resources and exit.
140 * @param param Parameter from the signal interface.
141 */
142void terminate(int param)
143{
144 updater->get_logger()->print_caught_sigterm();
c5a6b1fe 145 exit_now = true;
08a5a621 146} /*lint !e715 */
c5675c01
BS
147
148
149/**
150 * Signal SIGUSR1 caught, switching to offline mode.
151 * @param param Parameter from the signal interface.
152 */
153void switch_to_offline(int param)
154{
a6aac246 155 caught_sig_usr1 = true;
08a5a621 156} /*lint !e715 */
c5675c01
BS
157
158
159/**
64ff14c3 160 * Signal SIGHUP caught, reloading config.
39acb828 161 * @param param Parameter from the signal interface.
c5675c01
BS
162 */
163void reload_config(int param)
164{
4f4a6039 165 need_config_reload = true;
64ff14c3
BS
166} /*lint !e715 */
167
168
169/**
170 * Signal SIGUSR2 caught, switching to online mode.
171 * @param param Parameter from the signal interface.
172 */
173void switch_to_online(int param)
174{
a6aac246 175 caught_sig_usr2 = true;
64ff14c3
BS
176} /*lint !e715 */
177
178
179/**
180 * Signal SIGRTMIN caught, switching to online mode with webcheck enabled.
181 * @param param Parameter from the signal interface.
182 */
183void switch_to_online_webcheck(int param)
184{
a6aac246 185 caught_sig_rtmin1 = true;
08a5a621 186} /*lint !e715 */
c5675c01
BS
187
188
189/**
190 * Initialize the signals we handle.
e0080b78 191 * @return 0 if all is fine, -1 on error.
c5675c01 192 */
8bca3c5d 193int init_signals()
c5675c01 194{
8bca3c5d
BS
195 sighandler_t ret_val;
196 ret_val = signal(SIGTERM,terminate);
197 if ( ret_val == SIG_ERR )
667c672c
BS
198 {
199 updater->get_logger()->print_error_setting_signal("SIGTERM");
8bca3c5d 200 return -1;
667c672c 201 }
8bca3c5d
BS
202 ret_val = signal(SIGUSR1,switch_to_offline);
203 if ( ret_val == SIG_ERR )
667c672c
BS
204 {
205 updater->get_logger()->print_error_setting_signal("SIGUSR1");
8bca3c5d 206 return -1;
667c672c 207 }
8bca3c5d
BS
208 ret_val = signal(SIGHUP,reload_config);
209 if ( ret_val == SIG_ERR )
667c672c
BS
210 {
211 updater->get_logger()->print_error_setting_signal("SIGHUP");
8bca3c5d 212 return -1;
667c672c 213 }
64ff14c3
BS
214 ret_val = signal(SIGUSR2,switch_to_online);
215 if ( ret_val == SIG_ERR )
216 {
217 updater->get_logger()->print_error_setting_signal("SIGUSR2");
218 return -1;
219 }
220 ret_val = signal(SIGRTMIN,switch_to_online_webcheck);
221 if ( ret_val == SIG_ERR )
222 {
223 updater->get_logger()->print_error_setting_signal("SIGRTMIN");
224 return -1;
225 }
5ac72dd8
BS
226
227 return 0;
c5675c01
BS
228}
229
230
388f4ab0 231/**
584b9407
BS
232 * Try to run in daemon mode if enabled in config.
233 * @param daemon_mode True if process should detach to init (run as daemon), false if not detach to init.
234 * @return 0 if all is fine, -1 on error.
235 */
236int init_daemon_mode(bool daemon_mode)
237{
238 updater->get_logger()->print_daemon_mode(daemon_mode);
239 if ( daemon_mode == true )
240 {
241 int pid = fork();
242 if ( pid < 0 )
243 {
244 // error fork
245 updater->get_logger()->print_error_fork();
246 return -1;
247 }
248 else if ( pid > 0 )
249 {
250 // parent continues here
251 if ( write_pidfile(pid) != 0 )
252 {
253 if ( kill(pid,SIGTERM) != 0 )
e304c27b 254 {
584b9407 255 updater->get_logger()->print_error_kill_child(pid);
557b6f56 256 shutdown_parent(false,-1); /*lint !e534 */
e304c27b 257 }
584b9407 258 else
e304c27b 259 {
584b9407 260 updater->get_logger()->print_child_killed(pid);
557b6f56 261 shutdown_parent(true,-1); /*lint !e534 */
e304c27b 262 }
584b9407
BS
263 }
264 updater->get_logger()->print_runnig_as_daemon(pid);
557b6f56 265 shutdown_parent(false,0); /*lint !e534 */
584b9407
BS
266 }
267 // child starts here
268 }
e304c27b
BS
269 else
270 {
271 if ( write_pidfile(getpid()) != 0 )
272 {
557b6f56 273 shutdown(); /*lint !e534 */
e304c27b
BS
274 exit(-1);
275 }
276 }
584b9407
BS
277 return 0;
278}
279
280/**
b1be615b
BS
281 * @brief The main part.
282 * @param argc Number of arguments
283 * @param argv Command line arguments
284 * @return 0 if all is fine.
4545a371
BS
285 */
286int main(int argc, char *argv[])
287{
38060291 288 // initialize Updater
c3c84086 289 updater = Updater::Ptr(new Updater);
38060291 290
efbde536
BS
291 // load config and initialize helper classes
292 if ( updater->load_config(argc,argv) != 0 )
667c672c 293 return -1;
4545a371 294
388f4ab0 295 // open pidfile and check for running process
c5675c01 296 if ( check_for_running_process() != 0)
667c672c 297 return -1;
3434b35f 298
c5675c01 299 // init signal handling
8bca3c5d 300 if ( init_signals() != 0)
667c672c 301 return -1;
254bbf53 302
584b9407
BS
303 // init daemon_mode if enabled
304 if ( init_daemon_mode(updater->get_config()->get_daemon_mode()) != 0 )
305 return -1;
388f4ab0 306
dbaf4b42 307 // Should we start in offline mode?
a6aac246
TJ
308 bool is_online = !updater->get_config()->get_start_offline();
309 bool webcheck_enabled = updater->get_config()->get_webcheck_enabled();
dbaf4b42 310
c5a6b1fe
TJ
311 // One shot run if daemon mode is disabled
312 if (updater->get_config()->get_daemon_mode() != 1)
313 exit_now = true;
314
388f4ab0
BS
315 // service processing starts here
316 do
317 {
a6aac246
TJ
318 // Signal processing
319 if (caught_sig_usr1)
320 {
321 caught_sig_usr1 = false;
322 updater->get_logger()->print_caught_siguser1();
323
324 // Go offline
325 is_online = false;
326 } else if (caught_sig_usr2)
327 {
328 caught_sig_usr2 = false;
329 updater->get_logger()->print_caught_siguser2();
330
331 // Go online
332 is_online = true;
333 webcheck_enabled = false;
334 } else if (caught_sig_rtmin1)
335 {
336 caught_sig_rtmin1 = false;
337 updater->get_logger()->print_caught_sigrtmin();
338
339 // Go online - with webcheck
340 is_online = true;
341 webcheck_enabled = true;
342 }
343
344 // State handling
98dd88bd 345 if ( is_online == true )
c5675c01 346 {
46fffdd6 347 // Check if webcheck_enabled differs due to caught singnal then set it in config correspondingly
43f4565e 348 if ( updater->get_config()->get_webcheck_enabled() != webcheck_enabled ) /*lint !e731 */
46fffdd6
BS
349 updater->get_config()->set_webcheck_enabled(webcheck_enabled);
350
c5675c01
BS
351 // update all configured services
352 updater->update_services();
353 }
8bca3c5d
BS
354 else
355 {
50d63110 356 // We are in offline mode, do nothing, expect printing "offline mode".
8bca3c5d
BS
357 updater->get_logger()->print_offline_mode();
358 }
388f4ab0 359
4f4a6039
TJ
360 if (need_config_reload)
361 {
c5a6b1fe 362 updater->get_logger()->print_caught_sighup();
4f4a6039
TJ
363 need_config_reload = false;
364
365 if ( updater->reload_config() != 0 )
5b3f3f54
TJ
366 {
367 updater->get_logger()->print_conf_reload_failed_exit();
4f4a6039 368 exit(-1);
5b3f3f54 369 }
4f4a6039
TJ
370 }
371
a7beeb20 372 // Snore, snore... don't hog the cpu if we are in daemon_mode.
c5a6b1fe 373 if ( !exit_now )
557b6f56 374 sleep(10); /*lint !e534 */
c5a6b1fe 375 } while ( !exit_now );
4545a371 376
50d63110 377 // Serialize services to save their actual state.
e304c27b 378 if ( shutdown() != 0 )
667c672c 379 return -1;
2bc1878a 380
4545a371
BS
381 return 0;
382}