ports/net/pacemaker/files/patch-lib-services-services_linux.c
Tijl Coosemans dcf4604461 Add net/pacemaker.
Pacemaker is an advanced, scalable High-Availability cluster resource
manager for Linux-HA (Heartbeat) and/or Corosync.

It supports "n-node" clusters with significant capabilities for managing
resources and dependencies.

It will run scripts at initialization, when machines go up or down, when
related resources fail and can be configured to periodically check resource
health.

PR:		208221
Submitted by:	David Shane Holden <dpejesh@yahoo.com>
2016-03-24 15:56:07 +00: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);