3333
3434#include <netdb.h>
3535#include <sys/types.h>
36- #include <sys/un.h>
36+
37+ #ifdef WIN32
38+ #undef COLLECT_DAEMON
39+ #include <unistd.h>
40+ #undef gethostname
41+ #include <winsock2.h>
42+ #include <locale.h>
43+ #endif
3744
3845#if HAVE_LOCALE_H
3946#include <locale.h>
4956
5057static int loop = 0 ;
5158
52- static void * do_flush (void __attribute__((unused )) * arg ) {
53- INFO ("Flushing all data." );
54- plugin_flush (/* plugin = */ NULL ,
55- /* timeout = */ 0 ,
56- /* ident = */ NULL );
57- INFO ("Finished flushing all data." );
58- pthread_exit (NULL );
59- return NULL ;
60- }
61-
62- static void sig_int_handler (int __attribute__((unused )) signal ) { loop ++ ; }
63-
64- static void sig_term_handler (int __attribute__((unused )) signal ) { loop ++ ; }
65-
66- static void sig_usr1_handler (int __attribute__((unused )) signal ) {
67- pthread_t thread ;
68- pthread_attr_t attr ;
69-
70- /* flushing the data might take a while,
71- * so it should be done asynchronously */
72- pthread_attr_init (& attr );
73- pthread_attr_setdetachstate (& attr , PTHREAD_CREATE_DETACHED );
74- pthread_create (& thread , & attr , do_flush , NULL );
75- pthread_attr_destroy (& attr );
59+ static long hostname_len () {
60+ #ifdef WIN32
61+ return NI_MAXHOST ;
62+ #else
63+ long hostname_len = sysconf (_SC_HOST_NAME_MAX );
64+ if (hostname_len == -1 ) {
65+ hostname_len = NI_MAXHOST ;
66+ }
67+ return hostname_len ;
68+ #endif /* WIN32 */
7669}
7770
7871static int init_hostname (void ) {
@@ -82,13 +75,9 @@ static int init_hostname(void) {
8275 return 0 ;
8376 }
8477
85- long hostname_len = sysconf (_SC_HOST_NAME_MAX );
86- if (hostname_len == -1 ) {
87- hostname_len = NI_MAXHOST ;
88- }
89- char hostname [hostname_len ];
78+ char hostname [hostname_len ()];
9079
91- if (gethostname (hostname , hostname_len ) != 0 ) {
80+ if (gethostname (hostname , hostname_len () ) != 0 ) {
9281 fprintf (stderr , "`gethostname' failed and no "
9382 "hostname was configured.\n" );
9483 return -1 ;
@@ -328,122 +317,6 @@ static int do_shutdown(void) {
328317 return plugin_shutdown_all ();
329318} /* int do_shutdown */
330319
331- #if COLLECT_DAEMON
332- static int pidfile_create (void ) {
333- FILE * fh ;
334- const char * file = global_option_get ("PIDFile" );
335-
336- if ((fh = fopen (file , "w" )) == NULL ) {
337- ERROR ("fopen (%s): %s" , file , STRERRNO );
338- return 1 ;
339- }
340-
341- fprintf (fh , "%i\n" , (int )getpid ());
342- fclose (fh );
343-
344- return 0 ;
345- } /* static int pidfile_create (const char *file) */
346-
347- static int pidfile_remove (void ) {
348- const char * file = global_option_get ("PIDFile" );
349- if (file == NULL )
350- return 0 ;
351-
352- return unlink (file );
353- } /* static int pidfile_remove (const char *file) */
354- #endif /* COLLECT_DAEMON */
355-
356- #ifdef KERNEL_LINUX
357- static int notify_upstart (void ) {
358- char const * upstart_job = getenv ("UPSTART_JOB" );
359-
360- if (upstart_job == NULL )
361- return 0 ;
362-
363- if (strcmp (upstart_job , "collectd" ) != 0 ) {
364- WARNING ("Environment specifies unexpected UPSTART_JOB=\"%s\", expected "
365- "\"collectd\". Ignoring the variable." ,
366- upstart_job );
367- return 0 ;
368- }
369-
370- NOTICE ("Upstart detected, stopping now to signal readyness." );
371- raise (SIGSTOP );
372- unsetenv ("UPSTART_JOB" );
373-
374- return 1 ;
375- }
376-
377- static int notify_systemd (void ) {
378- int fd ;
379- const char * notifysocket ;
380- struct sockaddr_un su = {0 };
381- size_t su_size ;
382- char buffer [] = "READY=1\n" ;
383-
384- notifysocket = getenv ("NOTIFY_SOCKET" );
385- if (notifysocket == NULL )
386- return 0 ;
387-
388- if ((strlen (notifysocket ) < 2 ) ||
389- ((notifysocket [0 ] != '@' ) && (notifysocket [0 ] != '/' ))) {
390- ERROR ("invalid notification socket NOTIFY_SOCKET=\"%s\": path must be "
391- "absolute" ,
392- notifysocket );
393- return 0 ;
394- }
395- NOTICE ("Systemd detected, trying to signal readyness." );
396-
397- unsetenv ("NOTIFY_SOCKET" );
398-
399- #if defined(SOCK_CLOEXEC )
400- fd = socket (AF_UNIX , SOCK_DGRAM | SOCK_CLOEXEC , /* protocol = */ 0 );
401- #else
402- fd = socket (AF_UNIX , SOCK_DGRAM , /* protocol = */ 0 );
403- #endif
404- if (fd < 0 ) {
405- ERROR ("creating UNIX socket failed: %s" , STRERRNO );
406- return 0 ;
407- }
408-
409- su .sun_family = AF_UNIX ;
410- if (notifysocket [0 ] != '@' ) {
411- /* regular UNIX socket */
412- sstrncpy (su .sun_path , notifysocket , sizeof (su .sun_path ));
413- su_size = sizeof (su );
414- } else {
415- /* Linux abstract namespace socket: specify address as "\0foo", i.e.
416- * start with a null byte. Since null bytes have no special meaning in
417- * that case, we have to set su_size correctly to cover only the bytes
418- * that are part of the address. */
419- sstrncpy (su .sun_path , notifysocket , sizeof (su .sun_path ));
420- su .sun_path [0 ] = 0 ;
421- su_size = sizeof (sa_family_t ) + strlen (notifysocket );
422- if (su_size > sizeof (su ))
423- su_size = sizeof (su );
424- }
425-
426- if (sendto (fd , buffer , strlen (buffer ), MSG_NOSIGNAL , (void * )& su ,
427- (socklen_t )su_size ) < 0 ) {
428- ERROR ("sendto(\"%s\") failed: %s" , notifysocket , STRERRNO );
429- close (fd );
430- return 0 ;
431- }
432-
433- unsetenv ("NOTIFY_SOCKET" );
434- close (fd );
435- return 1 ;
436- }
437- #endif /* KERNEL_LINUX */
438-
439- struct cmdline_config {
440- _Bool test_config ;
441- _Bool test_readall ;
442- _Bool create_basedir ;
443- const char * configfile ;
444- _Bool daemonize ;
445- };
446-
447320void read_cmdline (int argc , char * * argv , struct cmdline_config * config ) {
448321 /* read options */
449322 while (1 ) {
@@ -530,20 +403,17 @@ int configure_collectd(struct cmdline_config *config) {
530403 return 0 ;
531404}
532405
533- int main (int argc , char * * argv ) {
534- #if COLLECT_DAEMON
535- pid_t pid ;
536- #endif
537- int exit_status = 0 ;
406+ void stop_collectd (void ) { loop ++ ; }
538407
408+ struct cmdline_config init_config (int argc , char * * argv ) {
539409 struct cmdline_config config = {
540410 .daemonize = 1 , .create_basedir = 1 , .configfile = CONFIGFILE ,
541411 };
542412
543413 read_cmdline (argc , argv , & config );
544414
545415 if (config .test_config )
546- return 0 ;
416+ exit ( EXIT_SUCCESS ) ;
547417
548418 if (optind < argc )
549419 exit_usage (1 );
@@ -554,110 +424,18 @@ int main(int argc, char **argv) {
554424 if ((status = configure_collectd (& config )) != 0 )
555425 exit (EXIT_FAILURE );
556426
557- #if COLLECT_DAEMON
558- /*
559- * fork off child
560- */
561- struct sigaction sig_chld_action = {.sa_handler = SIG_IGN };
562-
563- sigaction (SIGCHLD , & sig_chld_action , NULL );
564-
565- /*
566- * Only daemonize if we're not being supervised
567- * by upstart or systemd (when using Linux).
568- */
569- if (config .daemonize
570- #ifdef KERNEL_LINUX
571- && notify_upstart () == 0 && notify_systemd () == 0
572- #endif
573- ) {
574- int status ;
575-
576- if ((pid = fork ()) == -1 ) {
577- /* error */
578- fprintf (stderr , "fork: %s" , STRERRNO );
579- return 1 ;
580- } else if (pid != 0 ) {
581- /* parent */
582- /* printf ("Running (PID %i)\n", pid); */
583- return 0 ;
584- }
585-
586- /* Detach from session */
587- setsid ();
588-
589- /* Write pidfile */
590- if (pidfile_create ())
591- exit (2 );
592-
593- /* close standard descriptors */
594- close (2 );
595- close (1 );
596- close (0 );
597-
598- status = open ("/dev/null" , O_RDWR );
599- if (status != 0 ) {
600- ERROR ("Error: Could not connect `STDIN' to `/dev/null' (status %d)" ,
601- status );
602- return 1 ;
603- }
604-
605- status = dup (0 );
606- if (status != 1 ) {
607- ERROR ("Error: Could not connect `STDOUT' to `/dev/null' (status %d)" ,
608- status );
609- return 1 ;
610- }
611-
612- status = dup (0 );
613- if (status != 2 ) {
614- ERROR ("Error: Could not connect `STDERR' to `/dev/null', (status %d)" ,
615- status );
616- return 1 ;
617- }
618- } /* if (config.daemonize) */
619- #endif /* COLLECT_DAEMON */
620-
621- struct sigaction sig_pipe_action = {.sa_handler = SIG_IGN };
622-
623- sigaction (SIGPIPE , & sig_pipe_action , NULL );
624-
625- /*
626- * install signal handlers
627- */
628- struct sigaction sig_int_action = {.sa_handler = sig_int_handler };
629-
630- if (0 != sigaction (SIGINT , & sig_int_action , NULL )) {
631- ERROR ("Error: Failed to install a signal handler for signal INT: %s" ,
632- STRERRNO );
633- return 1 ;
634- }
635-
636- struct sigaction sig_term_action = {.sa_handler = sig_term_handler };
637-
638- if (0 != sigaction (SIGTERM , & sig_term_action , NULL )) {
639- ERROR ("Error: Failed to install a signal handler for signal TERM: %s" ,
640- STRERRNO );
641- return 1 ;
642- }
643-
644- struct sigaction sig_usr1_action = {.sa_handler = sig_usr1_handler };
427+ return config ;
428+ }
645429
646- if (0 != sigaction (SIGUSR1 , & sig_usr1_action , NULL )) {
647- ERROR ("Error: Failed to install a signal handler for signal USR1: %s" ,
648- STRERRNO );
649- return 1 ;
650- }
430+ int run_loop (_Bool test_readall ) {
431+ int exit_status = 0 ;
651432
652- /*
653- * run the actual loops
654- */
655433 if (do_init () != 0 ) {
656434 ERROR ("Error: one or more plugin init callbacks failed." );
657435 exit_status = 1 ;
658436 }
659437
660- if (config . test_readall ) {
438+ if (test_readall ) {
661439 if (plugin_read_all_once () != 0 ) {
662440 ERROR ("Error: one or more plugin read callbacks failed." );
663441 exit_status = 1 ;
@@ -675,10 +453,5 @@ int main(int argc, char **argv) {
675453 exit_status = 1 ;
676454 }
677455
678- #if COLLECT_DAEMON
679- if (config .daemonize )
680- pidfile_remove ();
681- #endif /* COLLECT_DAEMON */
682-
683456 return exit_status ;
684- } /* int main */
457+ } /* int run_loop */
0 commit comments