Преглед изворни кода

qnetd: Really daemonize

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse пре 10 година
родитељ
комит
f7ca447799
6 измењених фајлова са 210 додато и 19 уклоњено
  1. 36 10
      qdevices/corosync-qnetd.c
  2. 4 0
      qdevices/qnet-config.h
  3. 28 8
      qdevices/qnetd-log.c
  4. 7 1
      qdevices/qnetd-log.h
  5. 129 0
      qdevices/utils.c
  6. 6 0
      qdevices/utils.h

+ 36 - 10
qdevices/corosync-qnetd.c

@@ -49,6 +49,7 @@
 #include <syslog.h>
 #include <syslog.h>
 #include <signal.h>
 #include <signal.h>
 #include <errno.h>
 #include <errno.h>
+#include <unistd.h>
 
 
 #include "qnet-config.h"
 #include "qnet-config.h"
 #include "msg.h"
 #include "msg.h"
@@ -297,7 +298,8 @@ qnetd_client_check_tls(struct qnetd_instance *instance, struct qnetd_client *cli
 		}
 		}
 		break;
 		break;
 	default:
 	default:
-		errx(1, "Unhandled instance tls supported %u\n", instance->tls_supported);
+		qnetd_log(LOG_ERR, "Unhandled instance tls supported %u", instance->tls_supported);
+		exit(1);
 		break;
 		break;
 	}
 	}
 
 
@@ -721,8 +723,9 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 		    msg->seq_number,msg->quorate, &msg->nodes, &result_vote);
 		    msg->seq_number,msg->quorate, &msg->nodes, &result_vote);
 		break;
 		break;
 	default:
 	default:
-		errx(1, "qnetd_client_msg_received_node_list fatal error. "
+		qnetd_log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
 		    "Unhandled node_list_type");
 		    "Unhandled node_list_type");
+		exit(1);
 		break;
 		break;
 	}
 	}
 
 
@@ -771,8 +774,9 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 		}
 		}
 		break;
 		break;
 	default:
 	default:
-		errx(1, "qnetd_client_msg_received_node_list fatal error. "
+		qnetd_log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
 		    "Unhandled node_list_type");
 		    "Unhandled node_list_type");
+		exit(1);
 		break;
 		break;
 	}
 	}
 
 
@@ -1169,7 +1173,8 @@ qnetd_client_net_read(struct qnetd_instance *instance, struct qnetd_client *clie
 		dynar_clean(&client->receive_buffer);
 		dynar_clean(&client->receive_buffer);
 		break;
 		break;
 	default:
 	default:
-		errx(1, "Unhandled msgio_read error %d\n", res);
+		qnetd_log(LOG_ERR, "Unhandled msgio_read error %d\n", res);
+		exit(1);
 		break;
 		break;
 	}
 	}
 
 
@@ -1445,8 +1450,8 @@ usage(void)
 
 
 static void
 static void
 cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port, int *foreground,
 cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port, int *foreground,
-    int *debug_log, enum tlv_tls_supported *tls_supported, int *client_cert_required,
-    size_t *max_clients)
+    int *debug_log, int *bump_log_priority, enum tlv_tls_supported *tls_supported,
+    int *client_cert_required, size_t *max_clients)
 {
 {
 	int ch;
 	int ch;
 	char *ep;
 	char *ep;
@@ -1456,6 +1461,7 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port,
 	*host_port = QNETD_DEFAULT_HOST_PORT;
 	*host_port = QNETD_DEFAULT_HOST_PORT;
 	*foreground = 0;
 	*foreground = 0;
 	*debug_log = 0;
 	*debug_log = 0;
+	*bump_log_priority = 0;
 	*tls_supported = QNETD_DEFAULT_TLS_SUPPORTED;
 	*tls_supported = QNETD_DEFAULT_TLS_SUPPORTED;
 	*client_cert_required = QNETD_DEFAULT_TLS_CLIENT_CERT_REQUIRED;
 	*client_cert_required = QNETD_DEFAULT_TLS_CLIENT_CERT_REQUIRED;
 	*max_clients = QNETD_DEFAULT_MAX_CLIENTS;
 	*max_clients = QNETD_DEFAULT_MAX_CLIENTS;
@@ -1466,6 +1472,9 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port,
 			*foreground = 1;
 			*foreground = 1;
 			break;
 			break;
 		case 'd':
 		case 'd':
+			if (*debug_log) {
+				*bump_log_priority = 1;
+			}
 			*debug_log = 1;
 			*debug_log = 1;
 			break;
 			break;
 		case 'c':
 		case 'c':
@@ -1518,12 +1527,13 @@ main(int argc, char *argv[])
 	uint16_t host_port;
 	uint16_t host_port;
 	int foreground;
 	int foreground;
 	int debug_log;
 	int debug_log;
+	int bump_log_priority;
 	enum tlv_tls_supported tls_supported;
 	enum tlv_tls_supported tls_supported;
 	int client_cert_required;
 	int client_cert_required;
 	size_t max_clients;
 	size_t max_clients;
 
 
-	cli_parse(argc, argv, &host_addr, &host_port, &foreground, &debug_log, &tls_supported,
-	    &client_cert_required, &max_clients);
+	cli_parse(argc, argv, &host_addr, &host_port, &foreground, &debug_log, &bump_log_priority,
+	    &tls_supported, &client_cert_required, &max_clients);
 
 
 	if (foreground) {
 	if (foreground) {
 		qnetd_log_init(QNETD_LOG_TARGET_STDERR);
 		qnetd_log_init(QNETD_LOG_TARGET_STDERR);
@@ -1532,7 +1542,20 @@ main(int argc, char *argv[])
 	}
 	}
 
 
 	qnetd_log_set_debug(debug_log);
 	qnetd_log_set_debug(debug_log);
+	qnetd_log_set_priority_bump(bump_log_priority);
+
+	/*
+	 * Daemonize
+	 */
+	if (!foreground) {
+		utils_tty_detach();
+	}
+
+	if (utils_flock(QNETD_LOCK_FILE, getpid(), qnetd_log_printf) != 0) {
+		exit(1);
+	}
 
 
+	qnetd_log_printf(LOG_DEBUG, "Initializing nss");
 	if (nss_sock_init_nss((tls_supported != TLV_TLS_UNSUPPORTED ?
 	if (nss_sock_init_nss((tls_supported != TLV_TLS_UNSUPPORTED ?
 	    (char *)QNETD_NSS_DB_DIR : NULL)) != 0) {
 	    (char *)QNETD_NSS_DB_DIR : NULL)) != 0) {
 		qnetd_err_nss();
 		qnetd_err_nss();
@@ -1542,11 +1565,11 @@ main(int argc, char *argv[])
 		qnetd_err_nss();
 		qnetd_err_nss();
 	}
 	}
 
 
-
 	if (qnetd_instance_init(&instance, QNETD_MAX_CLIENT_RECEIVE_SIZE,
 	if (qnetd_instance_init(&instance, QNETD_MAX_CLIENT_RECEIVE_SIZE,
 	    QNETD_MAX_CLIENT_SEND_BUFFERS, QNETD_MAX_CLIENT_SEND_SIZE,
 	    QNETD_MAX_CLIENT_SEND_BUFFERS, QNETD_MAX_CLIENT_SEND_SIZE,
 	    tls_supported, client_cert_required, max_clients) == -1) {
 	    tls_supported, client_cert_required, max_clients) == -1) {
-		errx(1, "Can't initialize qnetd");
+		qnetd_log(LOG_ERR, "Can't initialize qnetd");
+		exit(1);
 	}
 	}
 	instance.host_addr = host_addr;
 	instance.host_addr = host_addr;
 	instance.host_port = host_port;
 	instance.host_port = host_port;
@@ -1555,6 +1578,7 @@ main(int argc, char *argv[])
 		qnetd_err_nss();
 		qnetd_err_nss();
 	}
 	}
 
 
+	qnetd_log_printf(LOG_DEBUG, "Creating listening socket");
 	instance.server.socket = nss_sock_create_listen_socket(instance.host_addr,
 	instance.server.socket = nss_sock_create_listen_socket(instance.host_addr,
 	    instance.host_port, PR_AF_INET6);
 	    instance.host_port, PR_AF_INET6);
 	if (instance.server.socket == NULL) {
 	if (instance.server.socket == NULL) {
@@ -1572,8 +1596,10 @@ main(int argc, char *argv[])
 	global_server_socket = instance.server.socket;
 	global_server_socket = instance.server.socket;
 	signal_handlers_register();
 	signal_handlers_register();
 
 
+	qnetd_log_printf(LOG_DEBUG, "Registering algorithms");
 	algorithms_register();
 	algorithms_register();
 
 
+	qnetd_log_printf(LOG_DEBUG, "QNetd ready to provide service");
 	/*
 	/*
 	 * MAIN LOOP
 	 * MAIN LOOP
 	 */
 	 */

+ 4 - 0
qdevices/qnet-config.h

@@ -61,6 +61,8 @@ extern "C" {
 #define QNETD_HEARTBEAT_INTERVAL_MIN		1000
 #define QNETD_HEARTBEAT_INTERVAL_MIN		1000
 #define QNETD_HEARTBEAT_INTERVAL_MAX		200000
 #define QNETD_HEARTBEAT_INTERVAL_MAX		200000
 
 
+#define QNETD_LOCK_FILE				LOCALSTATEDIR"/run/corosync-qnetd.pid"
+
 #define QDEVICE_NET_NSS_DB_DIR			COROSYSCONFDIR "/qdevice/net/node/nssdb"
 #define QDEVICE_NET_NSS_DB_DIR			COROSYSCONFDIR "/qdevice/net/node/nssdb"
 
 
 #define QDEVICE_NET_INITIAL_MSG_RECEIVE_SIZE	(1 << 15)
 #define QDEVICE_NET_INITIAL_MSG_RECEIVE_SIZE	(1 << 15)
@@ -81,6 +83,8 @@ extern "C" {
 
 
 #define QDEVICE_NET_MAX_CS_TRY_AGAIN		10
 #define QDEVICE_NET_MAX_CS_TRY_AGAIN		10
 
 
+#define QDEVICE_NET_LOCK_FILE			LOCALSTATEDIR"/run/corosync-qdevice-net.pid"
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 28 - 8
qdevices/qnetd-log.c

@@ -33,7 +33,6 @@
  */
  */
 
 
 #include <syslog.h>
 #include <syslog.h>
-#include <stdarg.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <time.h>
 #include <time.h>
 
 
@@ -42,6 +41,7 @@
 
 
 static int qnetd_log_config_target = 0;
 static int qnetd_log_config_target = 0;
 static int qnetd_log_config_debug = 0;
 static int qnetd_log_config_debug = 0;
+static int qnetd_log_config_priority_bump = 0;
 
 
 static const char qnetd_log_month_str[][4] = {
 static const char qnetd_log_month_str[][4] = {
     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -87,11 +87,11 @@ qnetd_log_syslog_prio_to_str(int priority)
 }
 }
 
 
 void
 void
-qnetd_log_printf(int priority, const char *format, ...)
+qnetd_log_vprintf(int priority, const char *format, va_list ap)
 {
 {
-	va_list ap;
 	time_t current_time;
 	time_t current_time;
 	struct tm tm_res;
 	struct tm tm_res;
+	int final_priority;
 
 
 	if (priority != LOG_DEBUG || (qnetd_log_config_debug)) {
 	if (priority != LOG_DEBUG || (qnetd_log_config_debug)) {
 		if (qnetd_log_config_target & QNETD_LOG_TARGET_STDERR) {
 		if (qnetd_log_config_target & QNETD_LOG_TARGET_STDERR) {
@@ -104,20 +104,33 @@ qnetd_log_printf(int priority, const char *format, ...)
 
 
 			fprintf(stderr, "%-7s ", qnetd_log_syslog_prio_to_str(priority));
 			fprintf(stderr, "%-7s ", qnetd_log_syslog_prio_to_str(priority));
 
 
-			va_start(ap, format);
 			vfprintf(stderr, format, ap);
 			vfprintf(stderr, format, ap);
 			fprintf(stderr, "\n");
 			fprintf(stderr, "\n");
-			va_end(ap);
 		}
 		}
 
 
 		if (qnetd_log_config_target & QNETD_LOG_TARGET_SYSLOG) {
 		if (qnetd_log_config_target & QNETD_LOG_TARGET_SYSLOG) {
-			va_start(ap, format);
-			vsyslog(priority, format, ap);
-			va_end(ap);
+			final_priority = priority;
+			if (qnetd_log_config_priority_bump && priority > LOG_INFO) {
+				final_priority = LOG_INFO;
+			}
+
+			vsyslog(final_priority, format, ap);
 		}
 		}
 	}
 	}
 }
 }
 
 
+void
+qnetd_log_printf(int priority, const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+
+	qnetd_log_vprintf(priority, format, ap);
+
+	va_end(ap);
+}
+
 void
 void
 qnetd_log_close(void)
 qnetd_log_close(void)
 {
 {
@@ -133,3 +146,10 @@ qnetd_log_set_debug(int enabled)
 
 
 	qnetd_log_config_debug = enabled;
 	qnetd_log_config_debug = enabled;
 }
 }
+
+void
+qnetd_log_set_priority_bump(int enabled)
+{
+
+	qnetd_log_config_priority_bump = enabled;
+}

+ 7 - 1
qdevices/qnetd-log.h

@@ -36,6 +36,7 @@
 #define _QNETD_LOG_H_
 #define _QNETD_LOG_H_
 
 
 #include <syslog.h>
 #include <syslog.h>
+#include <stdarg.h>
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
@@ -51,12 +52,17 @@ extern "C" {
 extern void		qnetd_log_init(int target);
 extern void		qnetd_log_init(int target);
 
 
 extern void		qnetd_log_printf(int priority, const char *format, ...)
 extern void		qnetd_log_printf(int priority, const char *format, ...)
-    __attribute__((__format__(__printf__, 2, 3)));;
+    __attribute__((__format__(__printf__, 2, 3)));
+
+extern void		qnetd_log_vprintf(int priority, const char *format, va_list ap)
+    __attribute__((__format__(__printf__, 2, 0)));
 
 
 extern void		qnetd_log_close(void);
 extern void		qnetd_log_close(void);
 
 
 extern void		qnetd_log_set_debug(int enabled);
 extern void		qnetd_log_set_debug(int enabled);
 
 
+extern void		qnetd_log_set_priority_bump(int enabled);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 129 - 0
qdevices/utils.c

@@ -33,11 +33,17 @@
  */
  */
 
 
 #include <sys/types.h>
 #include <sys/types.h>
+#include <sys/file.h>
 #include <arpa/inet.h>
 #include <arpa/inet.h>
 
 
+#include <err.h>
+#include <errno.h>
 #include <inttypes.h>
 #include <inttypes.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <unistd.h>
+#include <syslog.h>
 
 
 #include "utils.h"
 #include "utils.h"
 
 
@@ -61,3 +67,126 @@ utils_parse_bool_str(const char *str)
 
 
 	return (-1);
 	return (-1);
 }
 }
+
+int
+utils_flock(const char *lockfile, pid_t pid,
+    void (*log_printf)(int priority, const char *format, ...))
+{
+	struct flock lock;
+	char pid_s[17];
+	int fd_flag;
+	int lf;
+	int res;
+
+	res = 0;
+
+	lf = open(lockfile, O_WRONLY | O_CREAT, 0640);
+	if (lf == -1) {
+		log_printf(LOG_ERR, "Cannot create lock file. Error was %s", strerror(errno));
+
+		return (-1);
+	}
+
+retry_fcntl:
+	lock.l_type = F_WRLCK;
+	lock.l_start = 0;
+	lock.l_whence = SEEK_SET;
+	lock.l_len = 0;
+	if (fcntl(lf, F_SETLK, &lock) == -1) {
+		switch (errno) {
+		case EINTR:
+			goto retry_fcntl;
+			break;
+		case EAGAIN:
+		case EACCES:
+			log_printf(LOG_ERR, "Another instance is already running.");
+			res = -1;
+			goto error_close;
+			break;
+		default:
+			log_printf(LOG_ERR, "Cannot aquire lock. Error was %s", strerror(errno));
+			res = -1;
+			goto error_close;
+			break;
+		}
+	}
+
+	if (ftruncate(lf, 0) == -1) {
+		log_printf(LOG_ERR, "Cannot truncate lock file. Error was %s", strerror(errno));
+		res = -1;
+		goto error_close_unlink;
+	}
+
+	memset(pid_s, 0, sizeof(pid_s));
+	snprintf(pid_s, sizeof(pid_s) - 1, "%u\n", pid);
+
+retry_write:
+	if (write(lf, pid_s, strlen(pid_s)) != strlen(pid_s)) {
+		if (errno == EINTR) {
+			goto retry_write;
+		} else {
+			log_printf(LOG_ERR, "Cannot write pid to lock file. Error was %s",
+			    strerror(errno));
+			res = -1;
+			goto error_close_unlink;
+		}
+	}
+
+	if ((fd_flag = fcntl(lf, F_GETFD, 0)) == -1) {
+		log_printf(LOG_ERR, "Cannot get close-on exec flag for lock file. Error was %s",
+		    strerror(errno));
+		res = -1;
+		goto error_close_unlink;
+	}
+	fd_flag |= FD_CLOEXEC;
+	if (fcntl(lf, F_SETFD, fd_flag) == -1) {
+		log_printf(LOG_ERR, "Cannot set close-on-exec flag for lock file. Error was %s",
+		    strerror(errno));
+		res = -1;
+		goto error_close_unlink;
+	}
+
+	return (res);
+
+error_close_unlink:
+	unlink(lockfile);
+error_close:
+	close(lf);
+
+	return (res);
+}
+
+void
+utils_tty_detach(void)
+{
+	int devnull;
+
+	switch (fork()) {
+		case -1:
+			err(1, "Can't create child process");
+			break;
+		case 0:
+			break;
+		default:
+			exit(0);
+			break;
+	}
+
+	/* Create new session */
+	(void)setsid();
+
+	/*
+	 * Map stdin/out/err to /dev/null.
+	 */
+	devnull = open("/dev/null", O_RDWR);
+	if (devnull == -1) {
+		err(1, "Can't open /dev/null");
+	}
+
+	if (dup2(devnull, 0) < 0 || dup2(devnull, 1) < 0
+	    || dup2(devnull, 2) < 0) {
+		close(devnull);
+		err(1, "Can't dup2 stdin/out/err to /dev/null");
+	}
+	close(devnull);
+}

+ 6 - 0
qdevices/utils.h

@@ -44,6 +44,12 @@ extern "C" {
 
 
 extern int		utils_parse_bool_str(const char *str);
 extern int		utils_parse_bool_str(const char *str);
 
 
+extern int		utils_flock(const char *lockfile, pid_t pid,
+    void (*log_printf)(int priority, const char *format, ...)
+    __attribute__((__format__(__printf__, 2, 3))));
+
+extern void		utils_tty_detach(void);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif