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>
This commit is contained in:
Jan Friesse 2016-03-24 16:07:28 +01:00
parent 1ec61e33cc
commit ea7611a9dd
20 changed files with 479 additions and 36 deletions

View File

@ -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 \

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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");
}
}

View File

@ -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_ */

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

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

View File

@ -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
qdevices/unix-socket.c Normal file
View File

@ -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
qdevices/unix-socket.h Normal file
View File

@ -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_ */

View File

@ -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;
}

View File

@ -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);