removed the main while loop because if catch an exception cannot know state of pinger...
[pingcheck] / src / main.cpp
CommitLineData
91fcc471
TJ
1/*
2The software in this package is distributed under the GNU General
3Public License version 2 (with a special exception described below).
4
5A copy of GNU General Public License (GPL) is included in this distribution,
6in the file COPYING.GPL.
7
8As a special exception, if other files instantiate templates or use macros
9or inline functions from this file, or you compile this file and link it
10with other works to produce a work based on this file, this file
11does not by itself cause the resulting work to be covered
12by the GNU General Public License.
13
14However the source code for this file must still be made available
15in accordance with section (3) of the GNU General Public License.
16
17This exception does not invalidate any other reasons why a work based
18on this file might be covered by the GNU General Public License.
19*/
88714861 20#include <signal.h>
238da857 21#include <stdint.h>
88714861 22
c5e4bfa1 23#include <vector>
a4049623 24#include <iostream>
c5e4bfa1 25
e39cc3da 26#include <boost/asio.hpp>
8739a651 27#include <boost/foreach.hpp>
c1fff16a 28#include <boost/shared_ptr.hpp>
59733431
CH
29#include <boost/math/special_functions/round.hpp>
30#include <boost/numeric/conversion/cast.hpp>
365036be 31#include <boost/date_time/posix_time/posix_time_types.hpp>
4ea9706c 32
301610ca
GMF
33#include <daemonfunc.hpp>
34#include <logfunc.hpp>
8ef29e4a 35
780b0bca 36#include "boost_assert_handler.h"
9c55ecd3
GMF
37#include "config/configurationreader.h"
38#include "config/host.h"
72e54d1c 39#include "link/linkstatus.h"
3625c0e5 40#include "host/loglevel.h"
3fd74a53 41#include "host/pingprotocol.h"
8f66f529 42#include "host/pingscheduler.h"
41d175b0 43#include "icmp/icmppinger.h" // contains IcmpPacketDistributor
c5b4902d 44#include "dns/dnsmaster.h"
4ea9706c 45
780b0bca 46
ad8eb8ab 47using namespace std;
2bf8720f 48using boost::shared_ptr;
365036be 49using boost::posix_time::time_duration;
301610ca
GMF
50using I2n::Logger::GlobalLogger;
51
59733431
CH
52// a map from interval (in seconds) to delay (in seconds)
53typedef std::pair<int, float> IntervalCountPair;
54typedef std::map<int, float> DelayMap;
365036be
CH
55typedef shared_ptr<boost::asio::deadline_timer> TimerItem;
56
57const boost::posix_time::time_duration SIGNAL_CHECK_INTERVAL = boost::posix_time::seconds(1);
59733431 58
7cb9a340
GMF
59//-----------------------------------------------------------------------------
60// Declarations
61//-----------------------------------------------------------------------------
62
b588279a
CH
63typedef std::pair<bool, ConfigurationItem> GetConfigReturnType;
64GetConfigReturnType get_configuration(int, const char**);
7cb9a340
GMF
65LinkStatusItem get_status_notifier(const ConfigurationItem&);
66void init_logger();
5ba17410 67void set_log_output(const ConfigurationItem &);
59733431 68DelayMap calc_pinger_delays(const HostList &hosts);
a85f210b 69bool init_pingers(const IoServiceItem, const ConfigurationItem&,
365036be 70 const LinkStatusItem&, PingSchedulerList*);
7cb9a340
GMF
71void start_pingers(const PingSchedulerList&);
72void stop_pingers(const PingSchedulerList&);
7cb9a340 73
666388ba
CH
74void signal_handler_int(int param);
75void signal_handler_term(int param);
76void signal_handler_usr1(int param);
77void signal_handler_usr2(int param);
365036be 78void signal_checker( const boost::system::error_code &error );
666388ba 79void install_signal_handlers( const IoServiceItem io_service, const int config_log_level );
365036be
CH
80void reset_signal_handlers();
81
82// data required for signal handling (SIGINT, SIGTERM, ... )
83struct signal_data_struct
84{
963e98a2
CH
85 volatile sig_atomic_t signaled_flag_int;
86 volatile sig_atomic_t signaled_flag_term;
87 volatile sig_atomic_t signaled_flag_usr1;
88 volatile sig_atomic_t signaled_flag_usr2;
365036be
CH
89 IoServiceItem io_service;
90 void (*old_handler_int )(int);
91 void (*old_handler_term)(int);
92 void (*old_handler_usr1)(int);
93 void (*old_handler_usr2)(int);
94 bool stopped;
95 TimerItem check_timer;
96 int config_log_level;
97
98 signal_data_struct():
963e98a2
CH
99 signaled_flag_int( 0 ),
100 signaled_flag_term( 0 ),
101 signaled_flag_usr1( 0 ),
102 signaled_flag_usr2( 0 ),
365036be 103 io_service(),
425d0f07
CH
104 old_handler_int( 0 ),
105 old_handler_term( 0 ),
106 old_handler_usr1( 0 ),
107 old_handler_usr2( 0 ),
365036be
CH
108 stopped( false ),
109 check_timer(),
110 config_log_level( I2n::Logger::LogLevel::Notice )
111 { }
112
113};
7cb9a340
GMF
114//-----------------------------------------------------------------------------
115// Definitions
116//-----------------------------------------------------------------------------
35e8afe0 117
b588279a 118GetConfigReturnType get_configuration(
f2c0a5db 119 int argc,
5c3c6449 120 const char *argv[]
f2c0a5db
GMF
121)
122{
f2c0a5db
GMF
123 ConfigurationReader config_reader;
124 bool parsed_success = config_reader.parse( argc, argv );
b588279a 125 Configuration config_obj = config_reader.get_configuration();
f2c0a5db 126
b588279a
CH
127 ConfigurationItem configuration( new Configuration( config_obj ) );
128 GetConfigReturnType return_val( parsed_success, configuration );
129 return return_val;
f2c0a5db
GMF
130}
131
72e54d1c 132LinkStatusItem get_status_notifier(
f2c0a5db
GMF
133 const ConfigurationItem &configuration
134)
135{
136 int hosts_down_limit = configuration->get_hosts_down_limit();
137 int link_up_interval_in_min = configuration->get_link_up_interval_in_min();
1634f2a1 138 int link_down_interval_in_min = configuration->get_link_down_interval_in_min();
f2c0a5db 139 string status_notifier_cmd = configuration->get_status_notifier_cmd();
72e54d1c
GMF
140 LinkStatusItem link_analyzer(
141 new LinkStatus(
f2c0a5db
GMF
142 hosts_down_limit,
143 link_up_interval_in_min,
1634f2a1 144 link_down_interval_in_min,
f2c0a5db
GMF
145 status_notifier_cmd
146 )
147 );
148
149 return link_analyzer;
150}
151
88714861 152void init_logger()
301610ca 153{
0fd358ca
CH
154 // set default: log at level NOTICE to syslog and stderr
155 // to ensure that in case of faulty config, the error is noticed
365036be
CH
156 I2n::Logger::enable_syslog( I2n::Logger::Facility::User );
157 I2n::Logger::enable_stderr_log( true );
0fd358ca 158 I2n::Logger::set_log_level( I2n::Logger::LogLevel::Notice );
88714861
GMF
159}
160
5ba17410
GMF
161void set_log_output(
162 const ConfigurationItem &configuration
163)
164{
165 LogOutput log_output = configuration->get_log_output();
fda777ea 166 string log_file_name = configuration->get_log_file();
5ba17410
GMF
167 switch (log_output)
168 {
a85f210b
CH
169 case LogOutput_UNDEFINED:
170 GlobalLogger.warning() << "Unknown output target -- use syslog";
5ba17410 171 case LogOutput_SYSLOG:
ea16eb5e 172 GlobalLogger.info() << "Setting log output target to syslog" << endl;
5ba17410
GMF
173 I2n::Logger::enable_syslog(true);
174 I2n::Logger::enable_stderr_log(false);
175 I2n::Logger::enable_log_file(false);
ea16eb5e 176 GlobalLogger.info() << "Set log output target to syslog" << endl;
5ba17410
GMF
177 break;
178 case LogOutput_TERMINAL:
ea16eb5e 179 GlobalLogger.info() << "Setting log output target to terminal" << endl;
5ba17410
GMF
180 I2n::Logger::enable_syslog(false);
181 I2n::Logger::enable_stderr_log(true);
182 I2n::Logger::enable_log_file(false);
ea16eb5e
CH
183 GlobalLogger.info() << "Set log output target to terminal" << endl;
184 GlobalLogger.info() << "(check syslog for earlier messages)" << endl;
185 break;
fda777ea
CH
186 case LogOutput_FILE:
187 GlobalLogger.info() << "Setting log output target to file "
188 << log_file_name << endl;
189 I2n::Logger::enable_syslog(false);
190 I2n::Logger::enable_stderr_log(false);
191 I2n::Logger::enable_log_file(log_file_name);
192 GlobalLogger.info() << "Set log output target to file "
193 << log_file_name << endl;
194 GlobalLogger.info() << "(check syslog for earlier messages)" << endl;
195 break;
ea16eb5e
CH
196 default:
197 GlobalLogger.error() << "Unknown log output target!" << endl;
5ba17410
GMF
198 break;
199 }
200}
201
59733431
CH
202/**
203 * @brief calculate delay between pingers to evenly distribute them in time
204 *
205 * If there are many pingers with same interval, will get bursts of pings
206 * and none in-between. This function calculates delays for large numbers
0fd358ca 207 * of hosts with same ping intervals, to distribute them as evenly as
59733431
CH
208 * possible, right from the start (might diverge over time, anyway).
209 *
210 * Will not do much good for pingers with many different intervals, but
211 * then is not required anyway and does no(t much) harm.
212 *
213 * Called by init_pingers with
214 * @param hosts list of hosts as obtained from configuration
215 * @returns a map from ping interval to delay between pingers of that interval
216 */
217DelayMap calc_pinger_delays(const HostList &hosts)
218{
219 // first step: count number of hosts with same intervals
220 DelayMap delay_shifts;
221 int curr_interval;
c086c9e6 222 BOOST_FOREACH( const HostItem &host, hosts )
59733431
CH
223 {
224 curr_interval = host->get_interval_in_sec();
225 if (! curr_interval)
226 delay_shifts[curr_interval] = 1.0f;
227 else
228 delay_shifts[curr_interval] += 1.0f;
229 }
230
231 // second step: divide intervals by counts, round to int
232 // --> for 18 pingers with a 30s interval, get 30s/18 = 1.66667
233 BOOST_FOREACH( IntervalCountPair interval_and_count, delay_shifts )
234 delay_shifts[interval_and_count.first] =
235 boost::numeric_cast<float>(interval_and_count.first) /
236 interval_and_count.second;
237
238 return delay_shifts;
239}
240
a85f210b 241bool init_pingers(
365036be 242 const IoServiceItem io_service,
f2c0a5db 243 const ConfigurationItem &configuration,
72e54d1c 244 const LinkStatusItem &status_notifier,
f2c0a5db
GMF
245 PingSchedulerList *scheduler_list
246)
2666d1f7 247{
035c2305 248 string default_network_interface = configuration->get_source_network_interface();
f2c0a5db 249 int ping_fail_limit = configuration->get_ping_fail_limit();
079d19ab 250 int ping_reply_timeout = configuration->get_ping_reply_timeout();
301610ca 251
096b06ef
CH
252 // remove some hosts at random
253 configuration->randomize_hosts();
254
59733431
CH
255 // calculate delays between pingers of same interval
256 DelayMap delay_shifts = calc_pinger_delays(configuration->get_hosts());
257
258 // setup memory for assigned delays
259 DelayMap delays;
260 BOOST_FOREACH( IntervalCountPair interval_and_delay, delay_shifts )
261 delays[interval_and_delay.first] = 0.0f;
262
f2c0a5db 263 HostList hosts = configuration->get_hosts();
a85f210b
CH
264
265 if (hosts.empty())
266 return false;
267
e01cc130 268 BOOST_FOREACH( const HostItem &host, hosts )
2666d1f7 269 {
f2c0a5db 270 string destination_address = host->get_address();
238da857 271 uint16_t destination_port = host->get_port();
035c2305 272 string host_network_interface = host->get_source_network_interface();
27c5a2be
GMF
273 string network_interface = ( host_network_interface == "default" ) ?
274 default_network_interface :
275 host_network_interface;
086e2cc0 276 PingProtocolList protocol_list = host->get_ping_protocol_list();
f2c0a5db 277 int ping_interval_in_sec = host->get_interval_in_sec();
59733431
CH
278
279 // get delay for this scheduler and update assigned delays
280 int current_delay = boost::math::iround(delays[ping_interval_in_sec]);
281 delays[ping_interval_in_sec] += delay_shifts[ping_interval_in_sec];
91aa83f9
CH
282 int n_parallel_pings = 10;
283 int parallel_ping_delay = 100; // ms
59733431 284
f2c0a5db
GMF
285 PingSchedulerItem scheduler(
286 new PingScheduler(
fc7ae593 287 io_service,
035c2305 288 network_interface,
f2c0a5db 289 destination_address,
1309d0e4 290 destination_port,
086e2cc0 291 protocol_list,
f2c0a5db
GMF
292 ping_interval_in_sec,
293 ping_fail_limit,
079d19ab 294 ping_reply_timeout,
59733431 295 status_notifier,
91aa83f9
CH
296 current_delay,
297 n_parallel_pings,
298 parallel_ping_delay
f1bf3249 299 )
c1fff16a 300 );
f2c0a5db
GMF
301 scheduler_list->push_back( scheduler );
302 }
a85f210b
CH
303
304 return true;
f2c0a5db 305}
c1fff16a 306
f2c0a5db
GMF
307void start_pingers(
308 const PingSchedulerList &scheduler_list
309)
310{
88714861 311 // start each ping scheduler
e01cc130 312 BOOST_FOREACH( const PingSchedulerItem &scheduler, scheduler_list )
365036be 313 scheduler->start_pinging();
88714861
GMF
314}
315
316void stop_pingers(
317 const PingSchedulerList &scheduler_list
318)
319{
1d1ae364
TJ
320 // Stop each ping scheduler
321 GlobalLogger.info() << "Telling all pingers to stop";
e01cc130 322 BOOST_FOREACH( const PingSchedulerItem &scheduler, scheduler_list )
88714861 323 {
365036be 324 scheduler->stop_pinging();
88714861 325 }
0470811e 326
1ece191b 327 IcmpPacketDistributor::clean_up_all();
88714861
GMF
328}
329
35e8afe0 330
365036be
CH
331// the one instance of signal_data_struct
332signal_data_struct signal_data;
333
0fd358ca 334
666388ba
CH
335/// registered as signal handler; just sets signal_data.signaled_flag
336void signal_handler_int(int param)
365036be 337{
963e98a2 338 signal_data.signaled_flag_int = 1;
666388ba
CH
339}
340void signal_handler_term(int param)
341{
963e98a2 342 signal_data.signaled_flag_term = 1;
666388ba
CH
343}
344void signal_handler_usr1(int param)
345{
963e98a2 346 signal_data.signaled_flag_usr1 = 1;
666388ba
CH
347}
348void signal_handler_usr2(int param)
349{
963e98a2 350 signal_data.signaled_flag_usr2 = 1;
35e8afe0
TJ
351}
352
0fd358ca
CH
353
354/// called regularly from io_service; checks signal_data.signal_flag
365036be 355void signal_checker( const boost::system::error_code &error )
35e8afe0 356{
365036be 357 bool want_stop = false;
35e8afe0 358
365036be
CH
359 if ( error )
360 { // there was an error in the timer
361 if ( error == boost::asio::error::operation_aborted )
35e8afe0 362 {
365036be
CH
363 GlobalLogger.error() << "Signal check timer was cancelled! Stopping io_service" << endl;
364 want_stop = true;
0b920e26
GMF
365 }
366 else
367 {
0fd358ca
CH
368 GlobalLogger.error() << "Signal check timer handler received error code " << error
369 << "! Stopping io_service" << endl;
365036be 370 want_stop = true;
0b920e26 371 }
35e8afe0 372 }
716deecb
CH
373 else {
374 if ( signal_data.signaled_flag_int )
375 {
963e98a2 376 signal_data.signaled_flag_int = 0;
716deecb
CH
377 GlobalLogger.notice() << "Received signal SIGINT --> will stop" << endl;
378 want_stop = true;
379 }
380 else if ( signal_data.signaled_flag_term )
381 {
963e98a2 382 signal_data.signaled_flag_term = 0;
716deecb
CH
383 GlobalLogger.notice() << "Received signal SIGTERM --> will stop" << endl;
384 want_stop = true;
385 }
386 else if ( signal_data.signaled_flag_usr1 )
365036be 387 {
963e98a2 388 signal_data.signaled_flag_usr1 = 0;
365036be
CH
389 int new_log_level = I2n::Logger::get_log_level()+1;
390 I2n::Logger::set_log_level( new_log_level );
666388ba 391 GlobalLogger.info() << "Received SIGUSR1 -- increased log level to "
365036be
CH
392 << I2n::Logger::get_log_level_string();
393 }
716deecb 394 else if ( signal_data.signaled_flag_usr2 )
365036be 395 {
963e98a2 396 signal_data.signaled_flag_usr2 = 0;
365036be 397 I2n::Logger::set_log_level( signal_data.config_log_level );
666388ba 398 GlobalLogger.info() << "Received SIGUSR2 -- reset log level to normal ("
365036be
CH
399 << I2n::Logger::get_log_level_string() << ")";
400 }
365036be 401 }
fc7ae593 402
365036be
CH
403 if ( want_stop )
404 { // interrupt infinite loop in main and asio event loop
405 signal_data.stopped = true;
406 signal_data.io_service->stop();
fc7ae593
CH
407 }
408 else
365036be 409 { // re-schedule timer
365036be
CH
410 signal_data.check_timer->expires_from_now( SIGNAL_CHECK_INTERVAL );
411 signal_data.check_timer->async_wait( signal_checker );
fc7ae593
CH
412 }
413}
414
365036be 415/// register own signal handlers; see reset_signal_handlers for undo
666388ba 416void install_signal_handlers( const IoServiceItem io_service, const int config_log_level )
fc7ae593 417{
963e98a2
CH
418 signal_data.signaled_flag_int = 0;
419 signal_data.signaled_flag_term = 0;
420 signal_data.signaled_flag_usr1 = 0;
421 signal_data.signaled_flag_usr2 = 0;
365036be 422 signal_data.config_log_level = config_log_level;
fc7ae593
CH
423
424 // install own signal handlers
666388ba
CH
425 signal_data.old_handler_int = signal(SIGINT, signal_handler_int);
426 signal_data.old_handler_term = signal(SIGTERM, signal_handler_term);
427 signal_data.old_handler_usr1 = signal(SIGUSR1, signal_handler_usr1);
428 signal_data.old_handler_usr2 = signal(SIGUSR2, signal_handler_usr2);
fc7ae593
CH
429 if ( signal_data.old_handler_int == SIG_ERR ||
430 signal_data.old_handler_term == SIG_ERR ||
431 signal_data.old_handler_usr1 == SIG_ERR ||
432 signal_data.old_handler_usr2 == SIG_ERR )
365036be
CH
433 throw runtime_error( string("Failed to install signal handler: ") + string(strerror(errno)) );
434
435 // create a timer and a shared pointer to it, so it does not get out of scope
436 TimerItem check_timer( new boost::asio::deadline_timer( *io_service ) );
fc7ae593 437
365036be 438 // remember the io_service and the timer
fc7ae593 439 signal_data.io_service = io_service;
365036be 440 signal_data.check_timer = check_timer;
fc7ae593 441
365036be
CH
442 // set the timer
443 check_timer->expires_from_now( SIGNAL_CHECK_INTERVAL );
444 check_timer->async_wait( signal_checker );
445 GlobalLogger.debug() << "signal timer set" << endl;
fc7ae593
CH
446}
447
666388ba 448/// reset handlers to the ones saved in install_signal_handlers
365036be 449void reset_signal_handlers()
f2c0a5db 450{
425d0f07
CH
451 void (*old_handler_int)(int) = 0;
452 void (*old_handler_term)(int) = 0;
453 void (*old_handler_usr1)(int) = 0;
454 void (*old_handler_usr2)(int) = 0;
455 if (signal_data.old_handler_int != 0 )
456 old_handler_int = signal(SIGINT , signal_data.old_handler_int);
457 if (signal_data.old_handler_term != 0 )
458 old_handler_term = signal(SIGTERM, signal_data.old_handler_term);
459 if (signal_data.old_handler_usr1 != 0 )
460 old_handler_usr1 = signal(SIGUSR1, signal_data.old_handler_usr1);
461 if (signal_data.old_handler_usr2 != 0 )
462 old_handler_usr2 = signal(SIGUSR2, signal_data.old_handler_usr2);
365036be
CH
463
464 if ( old_handler_int == SIG_ERR ||
465 old_handler_term == SIG_ERR ||
466 old_handler_usr1 == SIG_ERR ||
467 old_handler_usr2 == SIG_ERR )
468 throw runtime_error( string("Failed to reset signal handler: ") + string(strerror(errno)) );
469}
470
35e8afe0 471
365036be
CH
472int main( int argc, const char *argv[] )
473{
88714861 474 init_logger();
99ee8244 475 GlobalLogger.debug() << "logger initiated with default config";
f2c0a5db 476
6e8c880d 477 PingSchedulerList scheduler_list;
365036be 478 IoServiceItem io_service;
6e8c880d 479 int ret_code = 0;
ad83004d 480
6e8c880d 481 try
f2c0a5db 482 {
b588279a
CH
483 GetConfigReturnType success_and_config = get_configuration( argc, argv );
484 ConfigurationItem configuration = success_and_config.second;
485
486 if ( configuration->get_print_version() ) // do this even if parsing of config failed
487 {
a85f210b
CH
488 GlobalLogger.debug() << "Printing version info ("
489 << VERSION_STRING << "." << VERSION_REVISION_STRING
490 << " build " << __DATE__
491 << ") and exit" << endl;
492 cout << PROJECT_NAME << " version "
493 << VERSION_STRING << "." << VERSION_REVISION_STRING
494 << " build " << __DATE__
495 << endl;
b588279a
CH
496 return 0;
497 }
498
499 if ( ! success_and_config.first )
6e8c880d 500 {
b588279a
CH
501 GlobalLogger.error() << "Could not read/parse configuration!";
502 GlobalLogger.debug() << "Return 1 immediately" << endl;
fc7ae593
CH
503 return 1;
504 }
b588279a 505 GlobalLogger.debug() << "Start setup" << endl;
1d1ae364 506
fc7ae593 507 int log_level = configuration->get_log_level();
365036be 508 I2n::Logger::set_log_level( log_level );
fc7ae593 509 GlobalLogger.info() << "Set LogLevel to " << I2n::Logger::get_log_level_string() << endl;
5ba17410 510
fc7ae593 511 set_log_output( configuration );
a85f210b
CH
512 GlobalLogger.notice() << "started pingcheck version "
513 << VERSION_STRING << "." << VERSION_REVISION_STRING
514 << " build " << __DATE__
515 << endl;
f2c0a5db 516
fc7ae593
CH
517 bool daemon_mode = configuration->get_daemon();
518 if ( daemon_mode )
519 {
520 I2n::Daemon::daemonize();
521 }
f2c0a5db 522
fc7ae593 523 LinkStatusItem status_notifier = get_status_notifier( configuration );
f2c0a5db 524
365036be
CH
525 IoServiceItem io_service_temp( new boost::asio::io_service() );
526 io_service_temp.swap( io_service );
527 io_service_temp.reset();
fc7ae593 528
9490a7bd
CH
529 // create Dns master
530 boost::asio::ip::address name_server_ip =
531 boost::asio::ip::address::from_string(
532 configuration->get_nameserver() );
a85f210b 533 int max_recursion_count = 10; // could make a config var some time
9490a7bd
CH
534 DnsMaster::create_master(
535 io_service,
536 name_server_ip,
537 configuration->get_resolved_ip_ttl_threshold(),
f833126b 538 configuration->get_min_time_between_resolves(),
9490a7bd 539 configuration->get_max_address_resolution_attempts(),
cd71d095 540 max_recursion_count,
9490a7bd
CH
541 configuration->get_dns_cache_file() );
542
a85f210b
CH
543 if ( !init_pingers(io_service, configuration, status_notifier,
544 &scheduler_list) )
545 {
546 GlobalLogger.error() << "Could not initialize pingers or no hosts "
547 << "given to ping --> exit";
548 return 2;
549 }
fc7ae593 550
666388ba 551 install_signal_handlers( io_service, log_level );
88714861 552
365036be 553 start_pingers( scheduler_list );
6e8c880d 554 }
aaff53da 555 catch ( const std::exception &ex )
6e8c880d 556 {
fc7ae593 557 GlobalLogger.error() << "Uncaught exception. " << ex.what() << endl;
a85f210b 558 ret_code = 3;
6e8c880d
CH
559 }
560 catch (...) {
fc7ae593 561 GlobalLogger.error() << "Caught unknown exception!" << endl;
a85f210b 562 ret_code = 4;
6e8c880d 563 }
35e8afe0 564
365036be 565 if ( ret_code == 0 )
fc7ae593 566 {
747c13ca 567 GlobalLogger.info() << "starting io_service main loop" << endl;
ad83004d 568
365036be 569 // call boost::asio main event loop, catching exceptions
7840efba
CH
570 try
571 {
572 io_service->run();
573 }
574 catch ( const std::exception &ex )
fc7ae593 575 {
7840efba
CH
576 GlobalLogger.error() << "Caught exception, will continue. " << ex.what() << endl;
577 }
578 catch (...) {
579 GlobalLogger.error() << "Caught unknown exception, will continue!" << endl;
fc7ae593
CH
580 }
581 }
582
6e8c880d
CH
583 // clean up
584 try
585 {
586 GlobalLogger.info() << "Cleaning up" << endl;
1d1ae364 587 stop_pingers( scheduler_list );
365036be 588 reset_signal_handlers();
ced28dc7 589 }
aaff53da 590 catch ( const std::exception &ex )
6e8c880d 591 {
fc7ae593 592 GlobalLogger.error() << "Uncaught exception while cleaning up: " << ex.what() << endl;
a85f210b 593 ret_code += 16;
6e8c880d
CH
594 }
595 catch (...) {
fc7ae593 596 GlobalLogger.error() << "Caught unknown exception while cleaning up!" << endl;
a85f210b 597 ret_code += 32;
6e8c880d 598 }
4ea9706c 599
365036be 600 GlobalLogger.notice() << "Pingcheck done " << endl;
6e8c880d 601 return ret_code;
4ea9706c 602}