mirror of
https://git.freebsd.org/ports.git
synced 2025-06-27 15:40:32 -04:00
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>
180 lines
5.3 KiB
C
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);
|