Explorar el Código

qdevice: Add support for daemonize

Also local unix socket is now created. In future this is going to be
used for qdevice-tool, for now it's used only for handling SIGINT and
SIGTERM.

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse hace 10 años
padre
commit
ea7611a9dd

+ 1 - 1
qdevices/Makefile.am

@@ -53,7 +53,7 @@ corosync_qdevice_SOURCES	= corosync-qdevice.c qdevice-cmap.c qdevice-instance.c
 				  qdevice-model.c \
 				  qdevice-model-net.c \
 				  qdevice-net-instance.c dynar.c send-buffer-list.c timer-list.c \
-				  msg.c msgio.c nss-sock.c tlv.c \
+				  msg.c msgio.c nss-sock.c tlv.c unix-socket.c qdevice-local-socket.c \
 				  qdevice-net-poll.c qdevice-net-send.c qdevice-net-votequorum.c \
 				  qdevice-net-socket.c qdevice-net-nss.c qdevice-net-msg-received.c \
 				  qdevice-net-cast-vote-timer.c qdevice-net-echo-request-timer.c \

+ 105 - 3
qdevices/corosync-qdevice.c

@@ -32,25 +32,126 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <config.h>
+#include <signal.h>
 
 #include "qdevice-config.h"
 #include "qdevice-cmap.h"
 #include "qdevice-log.h"
 #include "qdevice-model.h"
 #include "qdevice-votequorum.h"
+#include "qdevice-local-socket.h"
 #include "utils.h"
 
+struct qdevice_instance *global_instance;
+
+static void
+signal_int_handler(int sig)
+{
+	qdevice_log(LOG_DEBUG, "SIGINT received - closing local unix socket");
+	qdevice_local_socket_destroy(global_instance);
+}
+
+static void
+signal_term_handler(int sig)
+{
+	qdevice_log(LOG_DEBUG, "SIGTERM received - closing server socket");
+	qdevice_local_socket_destroy(global_instance);
+}
+
+static void
+signal_handlers_register(void)
+{
+	struct sigaction act;
+
+	act.sa_handler = signal_int_handler;
+	sigemptyset(&act.sa_mask);
+	act.sa_flags = SA_RESTART;
+
+	sigaction(SIGINT, &act, NULL);
+
+	act.sa_handler = signal_term_handler;
+	sigemptyset(&act.sa_mask);
+	act.sa_flags = SA_RESTART;
+
+	sigaction(SIGTERM, &act, NULL);
+}
+
+static void
+usage(void)
+{
+
+	printf("usage: %s [-dfh]\n", QDEVICE_PROGRAM_NAME);
+}
+
+static void
+cli_parse(int argc, char * const argv[], int *foreground, int *force_debug)
+{
+	int ch;
+
+	*foreground = 0;
+	*force_debug = 0;
+
+	while ((ch = getopt(argc, argv, "dfh")) != -1) {
+		switch (ch) {
+		case 'd':
+			*force_debug = 1;
+			break;
+		case 'f':
+			*foreground = 1;
+			break;
+		case 'h':
+		case '?':
+			usage();
+			exit(1);
+			break;
+		}
+	}
+}
+
 int
-main(void)
+main(int argc, char * const argv[])
 {
 	struct qdevice_instance instance;
+	int foreground;
+	int force_debug;
+	int lock_file;
+	int another_instance_running;
+
+	cli_parse(argc, argv, &foreground, &force_debug);
 
 	qdevice_instance_init(&instance);
+	global_instance = &instance;
+
 	qdevice_cmap_init(&instance);
-	qdevice_log_init(&instance);
+	qdevice_log_init(&instance, force_debug);
+
+	/*
+	 * Daemonize
+	 */
+	if (!foreground) {
+		utils_tty_detach();
+	}
+
+	if ((lock_file = utils_flock(QDEVICE_LOCK_FILE, getpid(), &another_instance_running)) == -1) {
+		if (another_instance_running) {
+			qdevice_log(LOG_ERR, "Another instance is running");
+		} else {
+			qdevice_log_err(LOG_ERR, "Can't aquire lock");
+		}
+
+		exit(1);
+	}
+
+	qdevice_log(LOG_DEBUG, "Initializing votequorum");
 	qdevice_votequorum_init(&instance);
 
+	qdevice_log(LOG_DEBUG, "Initializing local socket");
+	if (qdevice_local_socket_init(&instance) != 0) {
+		return (1);
+	}
+
+	signal_handlers_register();
+
 	qdevice_log(LOG_DEBUG, "Registering qdevice models");
 	qdevice_model_register_all();
 
@@ -87,6 +188,7 @@ main(void)
 	qdevice_log(LOG_DEBUG, "Destorying qdevice model");
 	qdevice_model_destroy(&instance);
 
+	qdevice_local_socket_destroy(&instance);
 	qdevice_votequorum_destroy(&instance);
 	qdevice_cmap_destroy(&instance);
 	qdevice_log_close(&instance);

+ 14 - 6
qdevices/corosync-qnetd.c

@@ -32,14 +32,14 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <config.h>
-
 #include <err.h>
 #include <errno.h>
 #include <getopt.h>
 #include <signal.h>
 #include <unistd.h>
 
+#include "qnet-config.h"
+
 #include "nss-sock.h"
 #include "qnetd-algorithm.h"
 #include "qnetd-instance.h"
@@ -224,7 +224,7 @@ static void
 usage(void)
 {
 
-	printf("usage: %s [-46df] [-l listen_addr] [-p listen_port] [-s tls]\n", QNETD_PROGRAM_NAME);
+	printf("usage: %s [-46dfh] [-l listen_addr] [-p listen_port] [-s tls]\n", QNETD_PROGRAM_NAME);
 	printf("%14s[-c client_cert_required] [-m max_clients]\n", "");
 }
 
@@ -247,7 +247,7 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port,
 	*max_clients = QNETD_DEFAULT_MAX_CLIENTS;
 	*address_family = PR_AF_UNSPEC;
 
-	while ((ch = getopt(argc, argv, "46fdc:l:m:p:s:")) != -1) {
+	while ((ch = getopt(argc, argv, "46dfhc:l:m:p:s:")) != -1) {
 		switch (ch) {
 		case '4':
 			*address_family = PR_AF_INET;
@@ -298,6 +298,7 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port,
 				errx(1, "tls must be one of on, off, req");
 			}
 			break;
+		case 'h':
 		case '?':
 			usage();
 			exit(1);
@@ -307,7 +308,7 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port,
 }
 
 int
-main(int argc, char *argv[])
+main(int argc, char * const argv[])
 {
 	struct qnetd_instance instance;
 	char *host_addr;
@@ -320,6 +321,7 @@ main(int argc, char *argv[])
 	size_t max_clients;
 	PRIntn address_family;
 	int lock_file;
+	int another_instance_running;
 
 	cli_parse(argc, argv, &host_addr, &host_port, &foreground, &debug_log, &bump_log_priority,
 	    &tls_supported, &client_cert_required, &max_clients, &address_family);
@@ -340,7 +342,13 @@ main(int argc, char *argv[])
 		utils_tty_detach();
 	}
 
-	if ((lock_file = utils_flock(QNETD_LOCK_FILE, getpid(), qnetd_log_printf)) == -1) {
+	if ((lock_file = utils_flock(QNETD_LOCK_FILE, getpid(), &another_instance_running)) == -1) {
+		if (another_instance_running) {
+			qnetd_log(LOG_ERR, "Another instance is running");
+		} else {
+			qnetd_log_err(LOG_ERR, "Can't acquire lock");
+		}
+
 		exit(1);
 	}
 

+ 5 - 1
qdevices/qdevice-config.h

@@ -35,6 +35,8 @@
 #ifndef _QDEVICE_CONFIG_H_
 #define _QDEVICE_CONFIG_H_
 
+#include <config.h>
+
 #include <qb/qbdefs.h>
 #include <qb/qblog.h>
 
@@ -47,10 +49,12 @@ extern "C" {
  * idea to change them as long as you are not 100% sure what you are doing.
  */
 #define QDEVICE_LOCK_FILE			LOCALSTATEDIR"/run/corosync-qdevice.pid"
+#define QDEVICE_LOCAL_SOCKET_FILE               LOCALSTATEDIR"/run/corosync-qdevice.sock"
+#define QDEVICE_LOCAL_SOCKET_BACKLOG		10
 
 #define QDEVICE_MAX_CS_TRY_AGAIN		10
 
-#define QDEVICE_PROGRAM_NAME			"qdevice-net"
+#define QDEVICE_PROGRAM_NAME			"corosync-qdevice"
 #define QDEVICE_LOG_SUBSYS			"QDEVICE"
 #define QDEVICE_LOG_DEFAULT_TO_STDERR		1
 #define QDEVICE_LOG_DEFAULT_TO_SYSLOG		1

+ 2 - 0
qdevices/qdevice-instance.h

@@ -61,6 +61,8 @@ struct qdevice_instance {
 	votequorum_handle_t votequorum_handle;
 	int votequorum_poll_fd;
 
+	int local_socket_fd;
+
 	enum qdevice_model_type model_type;
 
 	uint32_t node_id;

+ 73 - 0
qdevices/qdevice-local-socket.c

@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qdevice-config.h"
+#include "qdevice-log.h"
+#include "qdevice-local-socket.h"
+#include "unix-socket.h"
+
+int
+qdevice_local_socket_init(struct qdevice_instance *instance)
+{
+	int local_socket;
+
+	local_socket = unix_socket_server_create(QDEVICE_LOCAL_SOCKET_FILE, 1,
+	    QDEVICE_LOCAL_SOCKET_BACKLOG);
+	if (local_socket < 0) {
+		qdevice_log_err(LOG_ERR, "Can't create unix socket");
+		return (-1);
+	}
+
+	instance->local_socket_fd = local_socket;
+
+	return (0);
+}
+
+void
+qdevice_local_socket_destroy(struct qdevice_instance *instance)
+{
+
+	if (instance->local_socket_fd < 0) {
+		return ;
+	}
+
+	if (close(instance->local_socket_fd) != 0) {
+		qdevice_log_err(LOG_WARNING, "Can't close unix socket");
+	}
+
+	instance->local_socket_fd = -1;
+	if (unlink(QDEVICE_LOCAL_SOCKET_FILE) != 0) {
+		qdevice_log_err(LOG_WARNING, "Can't unlink unix socket");
+	}
+}

+ 55 - 0
qdevices/qdevice-local-socket.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QDEVICE_LOCAL_SOCKET_H_
+#define _QDEVICE_LOCAL_SOCKET_H_
+
+#include "qdevice-instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct qdevice_local_socket {
+};
+
+extern int		qdevice_local_socket_init(struct qdevice_instance *instance);
+
+extern void		qdevice_local_socket_destroy(struct qdevice_instance *instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDEVICE_LOCAL_SOCKET_H_ */

+ 9 - 1
qdevices/qdevice-log.c

@@ -36,6 +36,8 @@
 #include "qdevice-config.h"
 #include "utils.h"
 
+static int qdevice_log_global_force_debug;
+
 struct qdevice_log_syslog_names {
 	const char *prio_name;
 	int priority;
@@ -271,6 +273,10 @@ qdevice_log_configure(struct qdevice_instance *instance)
 	}
 	strcat(log_format_stderr, log_format_syslog);
 
+	if (qdevice_log_global_force_debug) {
+		debug = 1;
+	}
+
 	/*
 	 * Finally reconfigure log system
 	 */
@@ -289,8 +295,10 @@ qdevice_log_configure(struct qdevice_instance *instance)
 }
 
 void
-qdevice_log_init(struct qdevice_instance *instance)
+qdevice_log_init(struct qdevice_instance *instance, int force_debug)
 {
+	qdevice_log_global_force_debug = force_debug;
+
 	qb_log_init(QDEVICE_PROGRAM_NAME, QDEVICE_LOG_DEFAULT_SYSLOG_FACILITY,
 	    QDEVICE_LOG_DEFAULT_SYSLOG_PRIORITY);
 

+ 4 - 1
qdevices/qdevice-log.h

@@ -49,7 +49,10 @@ extern "C" {
 #define qdevice_log_nss(priority, str) qdevice_log(priority, "%s (%d): %s", \
     str, PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
 
-extern void		qdevice_log_init(struct qdevice_instance *instance);
+#define qdevice_log_err(priority, str) qdevice_log(priority, "%s (%d): %s", \
+    str, errno, strerror(errno));
+
+extern void		qdevice_log_init(struct qdevice_instance *instance, int force_debug);
 
 extern void		qdevice_log_configure(struct qdevice_instance *instance);
 

+ 2 - 5
qdevices/qdevice-model-net.c

@@ -32,9 +32,6 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-
-#include <config.h>
-
 #include <poll.h>
 
 #include "qdevice-model.h"
@@ -225,8 +222,8 @@ qdevice_model_net_run(struct qdevice_instance *instance)
 			    " Can't update cast vote timer vote");
 		}
 
-		if (net_instance->disconnect_reason ==
-		    QDEVICE_NET_DISCONNECT_REASON_COROSYNC_CONNECTION_CLOSED) {
+		if (net_instance->disconnect_reason == QDEVICE_NET_DISCONNECT_REASON_COROSYNC_CONNECTION_CLOSED ||
+		    net_instance->disconnect_reason == QDEVICE_NET_DISCONNECT_REASON_LOCAL_SOCKET_CLOSED) {
 			try_connect = 0;
 		}
 

+ 3 - 0
qdevices/qdevice-net-disconnect-reason.h

@@ -85,6 +85,9 @@ enum qdevice_net_disconnect_reason {
 	/* Can't dispatch cmap or votequroum. This cannot be overwritten and always means end of qdevice-net */
 	QDEVICE_NET_DISCONNECT_REASON_COROSYNC_CONNECTION_CLOSED,
 
+	/* Local socket closed is reasult of sigint */
+	QDEVICE_NET_DISCONNECT_REASON_LOCAL_SOCKET_CLOSED,
+
 	/* It was not possible to establish connection with qnetd */
 	QDEVICE_NET_DISCONNECT_REASON_CANT_CONNECT_TO_THE_SERVER,
 

+ 12 - 2
qdevices/qdevice-net-instance.c

@@ -51,7 +51,7 @@ qdevice_net_instance_init(struct qdevice_net_instance *instance, size_t initial_
     uint32_t sync_heartbeat_interval, uint32_t cast_vote_timer_interval,
     const char *host_addr, uint16_t host_port, const char *cluster_name,
     const struct tlv_tie_breaker *tie_breaker, uint32_t connect_timeout,
-    int force_ip_version, int cmap_fd, int votequorum_fd)
+    int force_ip_version, int cmap_fd, int votequorum_fd, int local_socket_fd)
 {
 
 	memset(instance, 0, sizeof(*instance));
@@ -94,6 +94,11 @@ qdevice_net_instance_init(struct qdevice_net_instance *instance, size_t initial_
 		return (-1);
 	}
 
+	if ((instance->local_socket_poll_fd = PR_CreateSocketPollFd(local_socket_fd)) == NULL) {
+		qdevice_log_nss(LOG_CRIT, "Can't create NSPR local socket poll fd");
+		return (-1);
+	}
+
 	return (0);
 }
 
@@ -136,6 +141,10 @@ qdevice_net_instance_destroy(struct qdevice_net_instance *instance)
 		qdevice_log_nss(LOG_WARNING, "Unable to close votequorum connection fd");
 	}
 
+	if (PR_DestroySocketPollFd(instance->local_socket_poll_fd) != PR_SUCCESS) {
+		qdevice_log_nss(LOG_WARNING, "Unable to close local socket poll fd");
+	}
+
 	return (0);
 }
 
@@ -337,7 +346,8 @@ qdevice_net_instance_init_from_cmap(struct qdevice_instance *instance)
 	    heartbeat_interval, sync_heartbeat_interval, cast_vote_timer_interval,
 	    host_addr, host_port, cluster_name, &tie_breaker, connect_timeout,
 	    force_ip_version,
-	    instance->cmap_poll_fd, instance->votequorum_poll_fd) == -1) {
+	    instance->cmap_poll_fd, instance->votequorum_poll_fd,
+	    instance->local_socket_fd) == -1) {
 		qdevice_log(LOG_ERR, "Can't initialize qdevice-net instance");
 		goto error_free_instance;
 	}

+ 2 - 1
qdevices/qdevice-net-instance.h

@@ -94,6 +94,7 @@ struct qdevice_net_instance {
 	int schedule_disconnect;
 	PRFileDesc *votequorum_poll_fd;
 	PRFileDesc *cmap_poll_fd;
+	PRFileDesc *local_socket_poll_fd;
 	struct tlv_ring_id last_sent_ring_id;
 	struct tlv_tie_breaker tie_breaker;
 	void *algorithm_data;
@@ -112,7 +113,7 @@ extern int		qdevice_net_instance_init(struct qdevice_net_instance *instance,
     uint32_t sync_heartbeat_interval, uint32_t cast_vote_timer_interval,
     const char *host_addr, uint16_t host_port, const char *cluster_name,
     const struct tlv_tie_breaker *tie_breaker, uint32_t connect_timeout, int force_ip_version,
-    int cmap_fd, int votequorum_fd);
+    int cmap_fd, int votequorum_fd, int local_socket_fd);
 
 extern void		qdevice_net_instance_clean(struct qdevice_net_instance *instance);
 

+ 27 - 0
qdevices/qdevice-net-poll.c

@@ -42,6 +42,7 @@
 enum qdevice_net_poll_pfd {
 	QDEVICE_NET_POLL_VOTEQUORUM,
 	QDEVICE_NET_POLL_CMAP,
+	QDEVICE_NET_POLL_LOCAL_SOCKET,
 	QDEVICE_NET_POLL_SOCKET,
 	QDEVICE_NET_POLL_MAX_PFDS
 };
@@ -142,6 +143,13 @@ qdevice_net_poll_err_socket(struct qdevice_net_instance *instance, const PRPollD
 	}
 }
 
+static void
+qdevice_net_poll_read_local_socket(struct qdevice_net_instance *instance)
+{
+
+//	qdevice_log(LOG_DEBUG, "READ ON LOCAL SOCKET");
+}
+
 int
 qdevice_net_poll(struct qdevice_net_instance *instance)
 {
@@ -160,6 +168,10 @@ qdevice_net_poll(struct qdevice_net_instance *instance)
 	pfds[QDEVICE_NET_POLL_CMAP].in_flags = PR_POLL_READ;
 	no_pfds++;
 
+	pfds[QDEVICE_NET_POLL_LOCAL_SOCKET].fd = instance->local_socket_poll_fd;
+	pfds[QDEVICE_NET_POLL_LOCAL_SOCKET].in_flags = PR_POLL_READ;
+	no_pfds++;
+
 	if (instance->state == QDEVICE_NET_INSTANCE_STATE_WAITING_CONNECT &&
 	    !instance->non_blocking_client.destroyed) {
 		pfds[QDEVICE_NET_POLL_SOCKET].fd = instance->non_blocking_client.socket;
@@ -190,6 +202,9 @@ qdevice_net_poll(struct qdevice_net_instance *instance)
 				case QDEVICE_NET_POLL_CMAP:
 					qdevice_net_poll_read_cmap(instance);
 					break;
+				case QDEVICE_NET_POLL_LOCAL_SOCKET:
+					qdevice_net_poll_read_local_socket(instance);
+					break;
 				default:
 					qdevice_log(LOG_CRIT, "Unhandled read on poll descriptor %u", i);
 					exit(1);
@@ -216,6 +231,18 @@ qdevice_net_poll(struct qdevice_net_instance *instance)
 				case QDEVICE_NET_POLL_SOCKET:
 					qdevice_net_poll_err_socket(instance, &pfds[i]);
 					break;
+				case QDEVICE_NET_POLL_LOCAL_SOCKET:
+					if (pfds[i].out_flags != PR_POLL_NVAL) {
+						qdevice_log(LOG_CRIT, "POLLERR (%u) on local socket",
+						    pfds[i].out_flags);
+						exit(1);
+					} else {
+						qdevice_log(LOG_DEBUG, "Local socket is closed");
+						instance->schedule_disconnect = 1;
+						instance->disconnect_reason =
+						    QDEVICE_NET_DISCONNECT_REASON_LOCAL_SOCKET_CLOSED;
+					}
+					break;
 				default:
 					qdevice_log(LOG_CRIT, "Unhandled error on poll descriptor %u", i);
 					exit(1);

+ 2 - 0
qdevices/qnet-config.h

@@ -35,6 +35,8 @@
 #ifndef _QNET_CONFIG_H_
 #define _QNET_CONFIG_H_
 
+#include <config.h>
+
 #include "tlv.h"
 
 #ifdef __cplusplus

+ 3 - 0
qdevices/qnetd-log.h

@@ -49,6 +49,9 @@ extern "C" {
 #define qnetd_log_nss(priority, str) qnetd_log_printf(priority, "%s (%d): %s", \
     str, PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
 
+#define qnetd_log_err(priority, str) qnetd_log_printf(priority, "%s (%d): %s", \
+    str, errno, strerror(errno))
+
 extern void		qnetd_log_init(int target);
 
 extern void		qnetd_log_printf(int priority, const char *format, ...)

+ 104 - 0
qdevices/unix-socket.c

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "unix-socket.h"
+
+static int
+unix_socket_set_non_blocking(int fd)
+{
+	int flags;
+
+	flags = fcntl(fd, F_GETFL, NULL);
+
+	if (flags < 0) {
+		return (-1);
+	}
+
+	flags |= O_NONBLOCK;
+	if (fcntl(fd, F_SETFL, flags) < 0) {
+		return (-1);
+        }
+
+        return (0);
+}
+
+int
+unix_socket_server_create(const char *path, int non_blocking, int backlog)
+{
+	int s;
+	struct sockaddr_un sun;
+
+	if (strlen(path) >= sizeof(sun.sun_path)) {
+		errno = ENAMETOOLONG;
+		return (-1);
+	}
+
+	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+		return (-1);
+	}
+
+	memset(&sun, 0, sizeof(sun));
+	sun.sun_family = AF_UNIX;
+
+	strncpy(sun.sun_path, path, sizeof(sun.sun_path));
+	unlink(path);
+	if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) != 0) {
+		close(s);
+
+		return (-1);
+	}
+
+	if (non_blocking) {
+		if (unix_socket_set_non_blocking(s) != 0) {
+			close(s);
+
+			return (-1);
+		}
+	}
+
+	if (listen(s, backlog) != 0) {
+		close(s);
+
+		return (-1);
+	}
+
+	return (s);
+}

+ 51 - 0
qdevices/unix-socket.h

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _UNIX_SOCKET_H_
+#define _UNIX_SOCKET_H_
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int		unix_socket_server_create(const char *path, int non_blocking, int backlog);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNIX_SOCKET_H_ */

+ 4 - 13
qdevices/utils.c

@@ -69,18 +69,17 @@ utils_parse_bool_str(const char *str)
 }
 
 int
-utils_flock(const char *lockfile, pid_t pid,
-    void (*log_printf)(int priority, const char *format, ...))
+utils_flock(const char *lockfile, pid_t pid, int *another_instance_running)
 {
 	struct flock lock;
 	char pid_s[17];
 	int fd_flag;
 	int lf;
 
+	*another_instance_running = 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);
 	}
 
@@ -96,18 +95,16 @@ retry_fcntl:
 			break;
 		case EAGAIN:
 		case EACCES:
-			log_printf(LOG_ERR, "Another instance is already running.");
+			*another_instance_running = 1;
 			goto error_close;
 			break;
 		default:
-			log_printf(LOG_ERR, "Cannot aquire lock. Error was %s", strerror(errno));
 			goto error_close;
 			break;
 		}
 	}
 
 	if (ftruncate(lf, 0) == -1) {
-		log_printf(LOG_ERR, "Cannot truncate lock file. Error was %s", strerror(errno));
 		goto error_close_unlink;
 	}
 
@@ -119,21 +116,15 @@ retry_write:
 		if (errno == EINTR) {
 			goto retry_write;
 		} else {
-			log_printf(LOG_ERR, "Cannot write pid to lock file. Error was %s",
-			    strerror(errno));
 			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));
 		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));
 		goto error_close_unlink;
 	}
 

+ 1 - 2
qdevices/utils.h

@@ -45,8 +45,7 @@ extern "C" {
 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))));
+    int *another_instance_running);
 
 extern void		utils_tty_detach(void);