You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by tr...@apache.org on 2014/07/23 23:18:27 UTC
svn commit: r1612946 - /qpid/dispatch/trunk/router/src/main.c
Author: tross
Date: Wed Jul 23 21:18:26 2014
New Revision: 1612946
URL: http://svn.apache.org/r1612946
Log:
DISPATCH-63 - Added daemon mode to the main module.
Modified:
qpid/dispatch/trunk/router/src/main.c
Modified: qpid/dispatch/trunk/router/src/main.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/router/src/main.c?rev=1612946&r1=1612945&r2=1612946&view=diff
==============================================================================
--- qpid/dispatch/trunk/router/src/main.c (original)
+++ qpid/dispatch/trunk/router/src/main.c Wed Jul 23 21:18:26 2014
@@ -21,6 +21,9 @@
#include <qpid/dispatch.h>
#include <signal.h>
#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include "config.h"
@@ -76,29 +79,210 @@ static void server_signal_handler(void*
qd_server_resume(dispatch);
}
-static void check() {
+static void check(int fd) {
if (qd_error_code()) {
qd_log(log_source, QD_LOG_CRITICAL, "Router start-up failed: %s", qd_error_message());
+ if (fd > 0)
+ write(fd, "X", 1);
exit(1);
}
}
+
+static void main_process(const char *config_path, const char *python_pkgdir, const char *qpid_dispatch_lib, int fd)
+{
+ qd_error_clear();
+ dispatch = qd_dispatch(python_pkgdir, qpid_dispatch_lib);
+ check(fd);
+ log_source = qd_log_source("MAIN"); /* Logging is initialized by qd_dispatch. */
+ qd_dispatch_load_config(dispatch, config_path);
+ check(fd);
+
+ (void)server_signal_handler; (void)thread_start_handler;(void)signal_handler;
+ qd_server_set_signal_handler(dispatch, server_signal_handler, 0);
+ qd_server_set_start_handler(dispatch, thread_start_handler, 0);
+
+ signal(SIGHUP, signal_handler);
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+ signal(SIGINT, signal_handler);
+
+ if (fd > 0) {
+ write(fd, "0", 1); // Success signal
+ close(fd);
+ }
+
+ qd_server_run(dispatch);
+ qd_dispatch_free(dispatch);
+
+ if (exit_with_sigint) {
+ signal(SIGINT, SIG_DFL);
+ kill(getpid(), SIGINT);
+ }
+}
+
+
+static void daemon_process(const char *config_path, const char *python_pkgdir, const char *qpid_dispatch_lib,
+ const char *pidfile, const char *user)
+{
+ int pipefd[2];
+
+ //
+ // This daemonization process is based on that outlined in the
+ // "daemon" manpage from Linux.
+ //
+
+ //
+ // Create an unnamed pipe for communication from the daemon to the main process
+ //
+ if (pipe(pipefd) < 0) {
+ perror("Error creating inter-process pipe");
+ exit(1);
+ }
+
+ //
+ // First fork
+ //
+ pid_t pid = fork();
+ if (pid == 0) {
+ //
+ // Child Process
+ //
+
+ //
+ // Detach any terminals and create an independent session
+ //
+ if (setsid() < 0) {
+ write(pipefd[1], "1", 1);
+ exit(0);
+ }
+
+ //
+ // Second fork
+ //
+ pid_t pid2 = fork();
+ if (pid2 == 0) {
+ close(pipefd[0]); // Close read end.
+
+ //
+ // Assign stdin, stdout, and stderr to /dev/null
+ //
+ close(2);
+ close(1);
+ close(0);
+ int fd = open("/dev/null", O_RDWR);
+ if (fd != 0) {
+ write(pipefd[1], "2", 1);
+ exit(0);
+ }
+ if (dup(fd) < 0) {
+ write(pipefd[1], "3", 1);
+ exit(0);
+ }
+ if (dup(fd) < 0) {
+ write(pipefd[1], "4", 1);
+ exit(0);
+ }
+
+ //
+ // Set the umask to 0
+ //
+ if (umask(0) < 0) {
+ write(pipefd[1], "5", 1);
+ exit(0);
+ }
+
+ //
+ // Set the current directory to "/" to avoid blocking
+ // mount points
+ //
+ if (chdir("/") < 0) {
+ write(pipefd[1], "6", 1);
+ exit(0);
+ }
+
+ //
+ // If a pidfile was provided, write the daemon pid there.
+ //
+ if (pidfile) {
+ FILE *pf = fopen(pidfile, "w");
+ if (pf == 0) {
+ write(pipefd[1], "7", 1);
+ exit(0);
+ }
+ fprintf(pf, "%d\n", getpid());
+ fclose(pf);
+ }
+
+ //
+ // If a user was provided, drop privileges to the user's
+ // privilege level.
+ //
+ if (user) {
+ struct passwd *pwd = getpwnam(user);
+ if (pwd == 0) {
+ write(pipefd[1], "8", 1);
+ exit(0);
+ }
+ if (setuid(pwd->pw_uid) < 0) {
+ write(pipefd[1], "9", 1);
+ exit(0);
+ }
+ if (setgid(pwd->pw_gid) < 0) {
+ write(pipefd[1], "A", 1);
+ exit(0);
+ }
+ }
+
+ main_process(config_path, python_pkgdir, qpid_dispatch_lib, pipefd[1]);
+ } else
+ //
+ // Exit first child
+ //
+ exit(0);
+ } else {
+ //
+ // Parent Process
+ // Wait for a success signal ('0') from the daemon process.
+ // If we get success, exit with 0. Otherwise, exit with 1.
+ //
+ char code;
+ close(pipefd[1]); // Close write end.
+ if (read(pipefd[0], &code, 1) < 0) {
+ perror("Error reading inter-process pipe");
+ exit(1);
+ }
+
+ if (code == '0')
+ exit(0);
+ fprintf(stderr, "Error occurred during daemon initialization, please see logs. [code=%c]\n", code);
+ exit(1);
+ }
+}
+
+
int main(int argc, char **argv)
{
#define DEFAULT_DISPATCH_PYTHON_DIR QPID_DISPATCH_HOME_INSTALLED "/python"
const char *config_path = DEFAULT_CONFIG_PATH;
const char *python_pkgdir = DEFAULT_DISPATCH_PYTHON_DIR;
const char *qpid_dispatch_lib = QPID_DISPATCH_LIB;
+ const char *pidfile = 0;
+ const char *user = 0;
+ bool daemon_mode = false;
static struct option long_options[] = {
{"config", required_argument, 0, 'c'},
{"include", required_argument, 0, 'I'},
+ {"daemon", no_argument, 0, 'd'},
+ {"pidfile", required_argument, 0, 'P'},
+ {"user", required_argument, 0, 'U'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
while (1) {
- int c = getopt_long(argc, argv, "c:I:h", long_options, 0);
+ int c = getopt_long(argc, argv, "c:I:dP:U:h", long_options, 0);
if (c == -1)
break;
@@ -111,12 +295,27 @@ int main(int argc, char **argv)
python_pkgdir = optarg;
break;
+ case 'd' :
+ daemon_mode = true;
+ break;
+
+ case 'P' :
+ pidfile = optarg;
+ break;
+
+ case 'U' :
+ user = optarg;
+ break;
+
case 'h' :
- printf("Usage: %s [OPTION]\n\n", argv[0]);
+ printf("Usage: %s [OPTIONS]\n\n", argv[0]);
printf(" -c, --config=PATH (%s)\n", DEFAULT_CONFIG_PATH);
printf(" Load configuration from file at PATH\n");
printf(" -I, --include=PATH (%s)\n", DEFAULT_DISPATCH_PYTHON_DIR);
printf(" Location of Dispatch's Python library\n");
+ printf(" -d, --daemon Run process as a SysV-style daemon\n");
+ printf(" -P, --pidfile If daemon, the file for the stored daemon pid\n");
+ printf(" -U, --user If daemon, the username to run as\n");
printf(" -h, --help Print this help\n");
exit(0);
@@ -125,30 +324,12 @@ int main(int argc, char **argv)
}
}
-
- qd_error_clear();
- dispatch = qd_dispatch(python_pkgdir, qpid_dispatch_lib);
- check();
- log_source = qd_log_source("MAIN"); /* Logging is initialized by qd_dispatch. */
- qd_dispatch_load_config(dispatch, config_path);
- check();
-
- (void)server_signal_handler; (void)thread_start_handler;(void)signal_handler;
- qd_server_set_signal_handler(dispatch, server_signal_handler, 0);
- qd_server_set_start_handler(dispatch, thread_start_handler, 0);
-
- signal(SIGHUP, signal_handler);
- signal(SIGQUIT, signal_handler);
- signal(SIGTERM, signal_handler);
- signal(SIGINT, signal_handler);
-
- qd_server_run(dispatch);
- qd_dispatch_free(dispatch);
-
- if (exit_with_sigint) {
- signal(SIGINT, SIG_DFL);
- kill(getpid(), SIGINT);
- }
+ if (daemon_mode)
+ daemon_process(config_path, python_pkgdir, qpid_dispatch_lib, pidfile, user);
+ else
+ main_process(config_path, python_pkgdir, qpid_dispatch_lib, -1);
return 0;
}
+
+
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org