opnsense-ports/net/pacemaker/files/patch-lib-services-services_linux.c
Franco Fichtner 934d69e7a3 */*: sync with upstream
Taken from: FreeBSD
2016-03-25 11:56:02 +01:00

180 lines
5.3 KiB
C

--- lib/services/services_linux.c.orig 2016-01-14 21:43:08 UTC
+++ lib/services/services_linux.c
@@ -457,13 +457,19 @@ action_launch_child(svc_action_t *op)
_exit(op->rc);
}
+#ifndef HAVE_SYS_SIGNALFD_H
+static int sigchld_pipe[2];
+
static void
-action_synced_wait(svc_action_t * op, sigset_t mask)
+sigchld_handler()
{
+ write(sigchld_pipe[1], "", 1);
+}
+#endif
-#ifndef HAVE_SYS_SIGNALFD_H
- CRM_ASSERT(FALSE);
-#else
+static void
+action_synced_wait(svc_action_t * op, sigset_t *mask)
+{
int status = 0;
int timeout = op->timeout;
int sfd = -1;
@@ -471,10 +477,14 @@ action_synced_wait(svc_action_t * op, si
struct pollfd fds[3];
int wait_rc = 0;
- sfd = signalfd(-1, &mask, SFD_NONBLOCK);
+#ifdef HAVE_SYS_SIGNALFD_H
+ sfd = signalfd(-1, mask, SFD_NONBLOCK);
if (sfd < 0) {
crm_perror(LOG_ERR, "signalfd() failed");
}
+#else
+ sfd = sigchld_pipe[0];
+#endif
fds[0].fd = op->opaque->stdout_fd;
fds[0].events = POLLIN;
@@ -503,6 +513,7 @@ action_synced_wait(svc_action_t * op, si
}
if (fds[2].revents & POLLIN) {
+#ifdef HAVE_SYS_SIGNALFD_H
struct signalfd_siginfo fdsi;
ssize_t s;
@@ -511,6 +522,12 @@ action_synced_wait(svc_action_t * op, si
crm_perror(LOG_ERR, "Read from signal fd %d failed", sfd);
} else if (fdsi.ssi_signo == SIGCHLD) {
+#else
+ if (1) {
+ /* Clear out the sigchld pipe. */
+ char ch;
+ while (read(sfd, &ch, 1) == 1);
+#endif
wait_rc = waitpid(op->pid, &status, WNOHANG);
if (wait_rc < 0){
@@ -583,10 +600,10 @@ action_synced_wait(svc_action_t * op, si
close(op->opaque->stdout_fd);
close(op->opaque->stderr_fd);
- close(sfd);
+#ifdef HAVE_SYS_SIGNALFD_H
+ close(sfd);
#endif
-
}
/* For an asynchronous 'op', returns FALSE if 'op' should be free'd by the caller */
@@ -596,9 +613,30 @@ services_os_action_execute(svc_action_t
{
int stdout_fd[2];
int stderr_fd[2];
+ struct stat st;
+ sigset_t *pmask;
+
+#ifdef HAVE_SYS_SIGNALFD_H
sigset_t mask;
sigset_t old_mask;
- struct stat st;
+#define sigchld_cleanup() { \
+ if (sigismember(&old_mask, SIGCHLD) == 0) { \
+ if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) { \
+ crm_perror(LOG_ERR, "sigprocmask() failed to unblock sigchld"); \
+ } \
+ } \
+}
+#else
+ struct sigaction sa;
+ struct sigaction old_sa;
+#define sigchld_cleanup() { \
+ if (sigaction(SIGCHLD, &old_sa, NULL) < 0) { \
+ crm_perror(LOG_ERR, "sigaction() failed to remove sigchld handler"); \
+ } \
+ close(sigchld_pipe[0]); \
+ close(sigchld_pipe[1]); \
+}
+#endif
if (pipe(stdout_fd) < 0) {
crm_err("pipe() failed");
@@ -620,13 +658,33 @@ services_os_action_execute(svc_action_t
}
if (synchronous) {
+#ifdef HAVE_SYS_SIGNALFD_H
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigemptyset(&old_mask);
if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) {
- crm_perror(LOG_ERR, "sigprocmask() failed");
+ crm_perror(LOG_ERR, "sigprocmask() failed to block sigchld");
+ }
+
+ pmask = &mask;
+#else
+ if(pipe(sigchld_pipe) == -1) {
+ crm_perror(LOG_ERR, "pipe() failed");
+ }
+
+ set_fd_opts(sigchld_pipe[0], O_NONBLOCK);
+ set_fd_opts(sigchld_pipe[1], O_NONBLOCK);
+
+ sa.sa_handler = sigchld_handler;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGCHLD, &sa, &old_sa) < 0) {
+ crm_perror(LOG_ERR, "sigaction() failed to set sigchld handler");
}
+
+ pmask = NULL;
+#endif
}
op->pid = fork();
@@ -645,6 +703,8 @@ services_os_action_execute(svc_action_t
if (!synchronous) {
return operation_finalize(op);
}
+
+ sigchld_cleanup();
return FALSE;
}
case 0: /* Child */
@@ -663,6 +723,10 @@ services_os_action_execute(svc_action_t
close(stderr_fd[1]);
}
+ if (synchronous) {
+ sigchld_cleanup();
+ }
+
action_launch_child(op);
}
@@ -677,14 +741,8 @@ services_os_action_execute(svc_action_t
set_fd_opts(op->opaque->stderr_fd, O_NONBLOCK);
if (synchronous) {
- action_synced_wait(op, mask);
-
- if (sigismember(&old_mask, SIGCHLD) == 0) {
- if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) {
- crm_perror(LOG_ERR, "sigprocmask() to unblocked failed");
- }
- }
-
+ action_synced_wait(op, pmask);
+ sigchld_cleanup();
} else {
crm_trace("Async waiting for %d - %s", op->pid, op->opaque->exec);