Also make sure the pipe is non blocking.
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/ipc_us.c | 56 ++--------------------------------------------
lib/loop_poll.c | 66 +++++++++++++++++++++++++++++++++++++++---------------
lib/util.c | 33 +++++++++++++++++++++++++++
lib/util_int.h | 12 ++++++++-
4 files changed, 93 insertions(+), 74 deletions(-)
diff --git a/lib/ipc_us.c b/lib/ipc_us.c
index 2f11daf..7b75522 100644
--- a/lib/ipc_us.c
+++ b/lib/ipc_us.c
@@ -73,43 +73,6 @@ static void socket_nosigpipe(int32_t s)
}
#endif
-static int32_t set_cloexec_flag(int32_t fd)
-{
- int32_t res;
- char error_str[100];
- int32_t oldflags = fcntl(fd, F_GETFD, 0);
-
- if (oldflags < 0) {
- oldflags = 0;
- }
- oldflags |= FD_CLOEXEC;
- res = fcntl(fd, F_SETFD, oldflags);
- if (res == -1) {
- res = -errno;
- strerror_r(errno, error_str, 100);
- qb_util_log(LOG_CRIT,
- "Could not set close-on-exit operation on socket: %s\n",
- error_str);
- }
- return res;
-}
-
-static int32_t set_nonblock_flag(int32_t fd)
-{
- int32_t res;
- char error_str[100];
-
- res = fcntl(fd, F_SETFL, O_NONBLOCK);
- if (res == -1) {
- res = -errno;
- strerror_r(errno, error_str, 100);
- qb_util_log(LOG_CRIT,
- "Could not set non-blocking operation on socket: %s\n",
- error_str);
- }
- return res;
-}
-
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
@@ -302,11 +265,7 @@ static int32_t qb_ipcc_us_sock_connect(const char *socket_name,
int32_t * sock_p
#ifdef SO_NOSIGPIPE
socket_nosigpipe(request_fd);
#endif /* SO_NOSIGPIPE */
- res = set_cloexec_flag(request_fd);
- if (res < 0) {
- goto error_connect;
- }
- res = set_nonblock_flag(request_fd);
+ res = qb_util_fd_nonblock_cloexec_set(request_fd);
if (res < 0) {
goto error_connect;
}
@@ -481,11 +440,7 @@ int32_t qb_ipcs_us_publish(struct qb_ipcs_service * s)
return res;
}
- res = set_cloexec_flag(s->server_sock);
- if (res < 0) {
- goto error_close;
- }
- res = set_nonblock_flag(s->server_sock);
+ res = qb_util_fd_nonblock_cloexec_set(s->server_sock);
if (res < 0) {
goto error_close;
}
@@ -816,12 +771,7 @@ retry_accept:
return 0; /* This is an error, but -1 would indicate disconnect from poll loop */
}
- res = set_cloexec_flag(new_fd);
- if (res < 0) {
- close(new_fd);
- return 0; /* This is an error, but -1 would indicate disconnect from poll loop */
- }
- res = set_nonblock_flag(new_fd);
+ res = qb_util_fd_nonblock_cloexec_set(new_fd);
if (res < 0) {
close(new_fd);
return 0; /* This is an error, but -1 would indicate disconnect from poll loop */
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index 8e667f9..12f317b 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -95,6 +95,8 @@ struct qb_poll_source {
int32_t not_enough_fds;
};
+static int32_t _qb_signal_add_to_jobs_(struct qb_loop* l,
+ struct qb_poll_entry* pe);
#ifdef HAVE_EPOLL
static int32_t poll_to_epoll_event(int32_t event)
@@ -741,8 +743,17 @@ struct qb_loop_sig {
static void _handle_real_signal_(int signal_num, siginfo_t * si, void *context)
{
int32_t sig = signal_num;
+ int32_t res = 0;
+
if (pipe_fds[1] > 0) {
- (void)write(pipe_fds[1], &sig, sizeof(int32_t));
+ try_again:
+ res = write(pipe_fds[1], &sig, sizeof(int32_t));
+ if (res == -1 && errno == EAGAIN) {
+ goto try_again;
+ } else if (res != sizeof(int32_t)) {
+ qb_util_log(LOG_ERR, "failed to write signal to pipe [%d]",
+ res);
+ }
}
}
@@ -764,14 +775,49 @@ static void signal_dispatch_and_take_back(struct qb_loop_item *
item,
struct qb_loop_source *
qb_loop_signals_create(struct qb_loop *l)
{
+ int32_t res = 0;
+ struct qb_poll_entry *pe;
struct qb_signal_source *s = calloc(1, sizeof(struct qb_signal_source));
+
s->s.l = l;
s->s.dispatch_and_take_back = signal_dispatch_and_take_back;
s->s.poll = NULL;
qb_list_init(&s->sig_head);
sigemptyset(&s->signal_superset);
+ if (pipe_fds[0] < 0) {
+ res = pipe(pipe_fds);
+ if (res == -1) {
+ res = -errno;
+ qb_util_log(LOG_ERR,
+ "Can't light pipe: %s",
+ strerror(-res));
+ goto error_exit;
+ }
+ (void)qb_util_fd_nonblock_cloexec_set(pipe_fds[0]);
+ (void)qb_util_fd_nonblock_cloexec_set(pipe_fds[1]);
+
+ res = _poll_add_(l, QB_LOOP_HIGH,
+ pipe_fds[0], POLLIN,
+ NULL, &pe);
+ if (res == 0) {
+ pe->poll_dispatch_fn = NULL;
+ pe->type = QB_SIGNAL;
+ pe->add_to_jobs = _qb_signal_add_to_jobs_;
+ } else {
+ qb_util_log(LOG_ERR,
+ "Can't smoke pipe: %s",
+ strerror(-res));
+ goto error_exit;
+ }
+ }
+
return (struct qb_loop_source *)s;
+
+ error_exit:
+ free(s);
+ errno = -res;
+ return NULL;
}
void qb_loop_signals_destroy(struct qb_loop *l)
@@ -860,9 +906,7 @@ int32_t qb_loop_signal_add(qb_loop_t *l,
qb_loop_signal_handle *handle)
{
struct qb_loop_sig *sig;
- struct qb_poll_entry *pe;
struct qb_signal_source *s;
- int32_t res = 0;
if (l == NULL || dispatch_fn == NULL) {
return -EINVAL;
@@ -882,22 +926,6 @@ int32_t qb_loop_signal_add(qb_loop_t *l,
qb_list_init(&sig->item.list);
qb_list_add_tail(&sig->item.list, &s->sig_head);
- if (pipe_fds[0] < 0) {
- pipe(pipe_fds);
- res = _poll_add_(l, QB_LOOP_HIGH,
- pipe_fds[0], POLLIN,
- NULL, &pe);
- if (res == 0) {
- pe->poll_dispatch_fn = NULL;
- pe->type = QB_SIGNAL;
- pe->add_to_jobs = _qb_signal_add_to_jobs_;
- } else {
- qb_util_log(LOG_ERR,
- "failed to setup pipe: %s",
- strerror(-res));
- }
- }
-
if (sigismember(&s->signal_superset, the_sig) != 1) {
_adjust_sigactions_(s);
}
diff --git a/lib/util.c b/lib/util.c
index 0ab5f1a..5238d4b 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -353,3 +353,36 @@ int32_t qb_util_circular_mmap(int32_t fd, void **buf, size_t bytes)
*buf = addr_orig;
return (0);
}
+
+int32_t qb_util_fd_nonblock_cloexec_set(int32_t fd)
+{
+ int32_t res;
+ char error_str[100];
+ int32_t oldflags = fcntl(fd, F_GETFD, 0);
+
+ if (oldflags < 0) {
+ oldflags = 0;
+ }
+ oldflags |= FD_CLOEXEC;
+ res = fcntl(fd, F_SETFD, oldflags);
+ if (res == -1) {
+ res = -errno;
+ strerror_r(errno, error_str, 100);
+ qb_util_log(LOG_CRIT,
+ "Could not set close-on-exit operation on fd: %s\n",
+ error_str);
+ return res;
+ }
+
+ res = fcntl(fd, F_SETFL, O_NONBLOCK);
+ if (res == -1) {
+ res = -errno;
+ strerror_r(errno, error_str, 100);
+ qb_util_log(LOG_CRIT,
+ "Could not set non-blocking operation on fd: %s\n",
+ error_str);
+ }
+ return res;
+}
+
+
diff --git a/lib/util_int.h b/lib/util_int.h
index 749937a..3e1f641 100644
--- a/lib/util_int.h
+++ b/lib/util_int.h
@@ -40,7 +40,7 @@ void _qb_util_log(const char *file_name,
* @param file (in) the name of the file to be used.
* @param bytes the size to truncate the file to.
* @param file_flags same as passed into open()
- * @return 0 (success) or -1 (error)
+ * @return 0 (success) or -errno
*/
int32_t qb_util_mmap_file_open(char *path, const char *file, size_t bytes,
uint32_t file_flags);
@@ -51,8 +51,16 @@ int32_t qb_util_mmap_file_open(char *path, const char *file, size_t
bytes,
* @param fd an open file to use to back the shared memory.
* @param buf (out) the pointer to the start of the memory.
* @param bytes the size of the shared memory.
- * @return 0 (success) or -1 (error)
+ * @return 0 (success) or -errno
*/
int32_t qb_util_circular_mmap(int32_t fd, void **buf, size_t bytes);
+
+/**
+ * Set O_NONBLOCK and FD_CLOEXEC on a file descriptor.
+ * @param fd the file descriptor.
+ * @return 0 (success) or -errno
+ */
+int32_t qb_util_fd_nonblock_cloexec_set(int32_t fd);
+
#endif /* QB_UTIL_INT_H_DEFINED */
--
1.7.3.1