/*\r
- * Copyright 2001-2007 Internet2\r
+ * Copyright 2001-2009 Internet2\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
const char* shar_prefix = NULL;\r
bool shar_checkonly = false;\r
bool shar_version = false;\r
-static int unlink_socket = 0;\r
+static bool unlink_socket = false;\r
const char* pidfile = NULL;\r
\r
#ifdef WIN32\r
\r
//_CrtSetAllocHook(MyAllocHook);\r
\r
- // Run the listener\r
if (!shar_checkonly) {\r
-\r
// Run the listener.\r
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
- fprintf(stderr, "listener failed to enter listen loop\n");\r
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
+ if (!listener->init(unlink_socket)) {\r
+ fprintf(stderr, "listener failed to initialize\n");\r
+ conf.term();\r
+ return -3;\r
+ }\r
+ else if (!listener->run(&shibd_shutdown)) {\r
+ fprintf(stderr, "listener failed during service\n");\r
+ listener->term();\r
+ conf.term();\r
return -3;\r
}\r
+ listener->term();\r
}\r
\r
conf.term();\r
\r
#else\r
\r
+int daemon_wait = 3;\r
+bool shibd_running = false;\r
+bool daemonize = true;\r
+\r
static void term_handler(int arg)\r
{\r
shibd_shutdown = true;\r
}\r
\r
+static void run_handler(int arg)\r
+{\r
+ shibd_running = true;\r
+}\r
+\r
+static void child_handler(int arg)\r
+{\r
+ // Terminate the parent's wait/sleep if the newly born daemon dies early.\r
+}\r
+\r
static int setup_signals(void)\r
{\r
struct sigaction sa;\r
if (sigaction(SIGTERM, &sa, NULL) < 0) {\r
return -1;\r
}\r
+\r
+ if (daemonize) {\r
+ memset(&sa, 0, sizeof (sa));\r
+ sa.sa_handler = run_handler;\r
+\r
+ if (sigaction(SIGUSR1, &sa, NULL) < 0) {\r
+ return -1;\r
+ }\r
+\r
+ memset(&sa, 0, sizeof (sa));\r
+ sa.sa_handler = child_handler;\r
+\r
+ if (sigaction(SIGCHLD, &sa, NULL) < 0) {\r
+ return -1;\r
+ }\r
+ }\r
+\r
return 0;\r
}\r
\r
fprintf(stderr, " -d\tinstallation prefix to use.\n");\r
fprintf(stderr, " -c\tconfig file to use.\n");\r
fprintf(stderr, " -x\tXML schema catalogs to use.\n");\r
- fprintf(stderr, " -t\tcheck configuration file for problems.\n");\r
+ fprintf(stderr, " -t\ttest configuration file for problems.\n");\r
fprintf(stderr, " -f\tforce removal of listener socket.\n");\r
+ fprintf(stderr, " -F\tstay in the foreground.\n");\r
fprintf(stderr, " -p\tpid file to use.\n");\r
+ fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n");\r
fprintf(stderr, " -v\tprint software version.\n");\r
fprintf(stderr, " -h\tprint this help message.\n");\r
exit(1);\r
{\r
int opt;\r
\r
- while ((opt = getopt(argc, argv, "d:c:x:p:ftvh")) > 0) {\r
+ while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {\r
switch (opt) {\r
case 'd':\r
shar_prefix=optarg;\r
shar_schemadir=optarg;\r
break;\r
case 'f':\r
- unlink_socket = 1;\r
+ unlink_socket = true;\r
+ break;\r
+ case 'F':\r
+ daemonize = false;\r
break;\r
case 't':\r
shar_checkonly=true;\r
+ daemonize=false;\r
break;\r
case 'v':\r
shar_version=true;\r
case 'p':\r
pidfile=optarg;\r
break;\r
+ case 'w':\r
+ if (optarg)\r
+ daemon_wait = atoi(optarg);\r
+ if (daemon_wait <= 0)\r
+ daemon_wait = 3;\r
+ break;\r
default:\r
return -1;\r
}\r
return -1;\r
}\r
\r
+ if (daemonize) {\r
+ // We must fork() early, while we're single threaded.\r
+ // StorageService cleanup thread is about to start.\r
+ switch (fork()) {\r
+ case 0:\r
+ break;\r
+ case -1:\r
+ perror("forking");\r
+ exit(EXIT_FAILURE);\r
+ default:\r
+ sleep(daemon_wait);\r
+ exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);\r
+ }\r
+ }\r
+\r
if (!conf.instantiate(shar_config)) {\r
fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
conf.term();\r
if (shar_checkonly)\r
fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
else {\r
+ // Init the listener.\r
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
+ if (!listener->init(unlink_socket)) {\r
+ fprintf(stderr, "listener failed to initialize\n");\r
+ conf.term();\r
+ return -3;\r
+ }\r
\r
- // Write the pid file\r
- if (pidfile) {\r
- FILE* pidf = fopen(pidfile, "w");\r
- if (pidf) {\r
- fprintf(pidf, "%d\n", getpid());\r
- fclose(pidf);\r
- } else {\r
- perror(pidfile); // keep running though\r
+ if (daemonize) {\r
+ if (setsid() == -1) {\r
+ perror("setsid");\r
+ exit(EXIT_FAILURE);\r
}\r
+ if (chdir("/") == -1) {\r
+ perror("chdir to root");\r
+ exit(EXIT_FAILURE);\r
+ }\r
+\r
+ if (pidfile) {\r
+ FILE* pidf = fopen(pidfile, "w");\r
+ if (pidf) {\r
+ fprintf(pidf, "%d\n", getpid());\r
+ fclose(pidf);\r
+ }\r
+ else {\r
+ perror(pidfile);\r
+ }\r
+ }\r
+\r
+ freopen("/dev/null", "r", stdin);\r
+ freopen("/dev/null", "w", stdout);\r
+ freopen("/dev/null", "w", stderr);\r
+\r
+ // Signal our parent that we are A-OK.\r
+ kill(getppid(), SIGUSR1);\r
}\r
\r
- // Run the listener\r
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
- fprintf(stderr, "listener failed to enter listen loop\n");\r
+ // Run the listener.\r
+ if (!listener->run(&shibd_shutdown)) {\r
+ fprintf(stderr, "listener failure during service\n");\r
+ listener->term();\r
+ conf.term();\r
+ if (pidfile)\r
+ unlink(pidfile);\r
return -3;\r
}\r
+ listener->term();\r
}\r
\r
conf.term();\r