pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
services_linux.c
Go to the documentation of this file.
1 /*
2  * Copyright 2010-2019 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #ifndef _GNU_SOURCE
11 # define _GNU_SOURCE
12 #endif
13 
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/wait.h>
17 #include <errno.h>
18 #include <unistd.h>
19 #include <dirent.h>
20 #include <string.h>
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 
24 #include "crm/crm.h"
25 #include "crm/common/mainloop.h"
26 #include "crm/services.h"
27 
28 #include "services_private.h"
29 
30 #if SUPPORT_CIBSECRETS
31 # include "crm/common/cib_secrets.h"
32 #endif
33 
34 /* We have two alternative ways of handling SIGCHLD when synchronously waiting
35  * for spawned processes to complete. Both rely on polling a file descriptor to
36  * discover SIGCHLD events.
37  *
38  * If sys/signalfd.h is available (e.g. on Linux), we call signalfd() to
39  * generate the file descriptor. Otherwise, we use the "self-pipe trick"
40  * (opening a pipe and writing a byte to it when SIGCHLD is received).
41  */
42 #ifdef HAVE_SYS_SIGNALFD_H
43 
44 // signalfd() implementation
45 
46 #include <sys/signalfd.h>
47 
48 // Everything needed to manage SIGCHLD handling
49 struct sigchld_data_s {
50  sigset_t mask; // Signals to block now (including SIGCHLD)
51  sigset_t old_mask; // Previous set of blocked signals
52 };
53 
54 // Initialize SIGCHLD data and prepare for use
55 static void
56 sigchld_setup(struct sigchld_data_s *data)
57 {
58  sigemptyset(&(data->mask));
59  sigaddset(&(data->mask), SIGCHLD);
60 
61  sigemptyset(&(data->old_mask));
62 
63  // Block SIGCHLD (saving previous set of blocked signals to restore later)
64  if (sigprocmask(SIG_BLOCK, &(data->mask), &(data->old_mask)) < 0) {
65  crm_perror(LOG_ERR, "sigprocmask() failed to block sigchld");
66  }
67 }
68 
69 // Get a file descriptor suitable for polling for SIGCHLD events
70 static int
71 sigchld_open(struct sigchld_data_s *data)
72 {
73  int fd;
74 
75  CRM_CHECK(data != NULL, return -1);
76 
77  fd = signalfd(-1, &(data->mask), SFD_NONBLOCK);
78  if (fd < 0) {
79  crm_perror(LOG_ERR, "signalfd() failed");
80  }
81  return fd;
82 }
83 
84 // Close a file descriptor returned by sigchld_open()
85 static void
86 sigchld_close(int fd)
87 {
88  if (fd > 0) {
89  close(fd);
90  }
91 }
92 
93 // Return true if SIGCHLD was received from polled fd
94 static bool
95 sigchld_received(int fd)
96 {
97  struct signalfd_siginfo fdsi;
98  ssize_t s;
99 
100  s = read(fd, &fdsi, sizeof(struct signalfd_siginfo));
101  if (s != sizeof(struct signalfd_siginfo)) {
102  crm_perror(LOG_ERR, "Read from signal fd %d failed", fd);
103 
104  } else if (fdsi.ssi_signo == SIGCHLD) {
105  return true;
106  }
107  return false;
108 }
109 
110 // Do anything needed after done waiting for SIGCHLD
111 static void
112 sigchld_cleanup(struct sigchld_data_s *data)
113 {
114  // Restore the original set of blocked signals
115  if ((sigismember(&(data->old_mask), SIGCHLD) == 0)
116  && (sigprocmask(SIG_UNBLOCK, &(data->mask), NULL) < 0)) {
117  crm_perror(LOG_ERR, "sigprocmask() failed to unblock sigchld");
118  }
119 }
120 
121 #else // HAVE_SYS_SIGNALFD_H not defined
122 
123 // Self-pipe implementation (see above for function descriptions)
124 
125 struct sigchld_data_s {
126  int pipe_fd[2]; // Pipe file descriptors
127  struct sigaction sa; // Signal handling info (with SIGCHLD)
128  struct sigaction old_sa; // Previous signal handling info
129 };
130 
131 // We need a global to use in the signal handler
132 volatile struct sigchld_data_s *last_sigchld_data = NULL;
133 
134 static void
135 sigchld_handler()
136 {
137  // We received a SIGCHLD, so trigger pipe polling
138  if ((last_sigchld_data != NULL)
139  && (last_sigchld_data->pipe_fd[1] >= 0)
140  && (write(last_sigchld_data->pipe_fd[1], "", 1) == -1)) {
141  crm_perror(LOG_TRACE, "Could not poke SIGCHLD self-pipe");
142  }
143 }
144 
145 static void
146 sigchld_setup(struct sigchld_data_s *data)
147 {
148  int rc;
149 
150  data->pipe_fd[0] = data->pipe_fd[1] = -1;
151 
152  if (pipe(data->pipe_fd) == -1) {
153  crm_perror(LOG_ERR, "pipe() failed");
154  }
155 
156  rc = crm_set_nonblocking(data->pipe_fd[0]);
157  if (rc < 0) {
158  crm_warn("Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
159  pcmk_strerror(rc), rc);
160  }
161  rc = crm_set_nonblocking(data->pipe_fd[1]);
162  if (rc < 0) {
163  crm_warn("Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
164  pcmk_strerror(rc), rc);
165  }
166 
167  // Set SIGCHLD handler
168  data->sa.sa_handler = sigchld_handler;
169  data->sa.sa_flags = 0;
170  sigemptyset(&(data->sa.sa_mask));
171  if (sigaction(SIGCHLD, &(data->sa), &(data->old_sa)) < 0) {
172  crm_perror(LOG_ERR, "sigaction() failed to set sigchld handler");
173  }
174 
175  // Remember data for use in signal handler
176  last_sigchld_data = data;
177 }
178 
179 static int
180 sigchld_open(struct sigchld_data_s *data)
181 {
182  CRM_CHECK(data != NULL, return -1);
183  return data->pipe_fd[0];
184 }
185 
186 static void
187 sigchld_close(int fd)
188 {
189  // Pipe will be closed in sigchld_cleanup()
190  return;
191 }
192 
193 static bool
194 sigchld_received(int fd)
195 {
196  char ch;
197 
198  // Clear out the self-pipe
199  while (read(fd, &ch, 1) == 1) /*omit*/;
200  return true;
201 }
202 
203 static void
204 sigchld_cleanup(struct sigchld_data_s *data)
205 {
206  // Restore the previous SIGCHLD handler
207  if (sigaction(SIGCHLD, &(data->old_sa), NULL) < 0) {
208  crm_perror(LOG_ERR, "sigaction() failed to remove sigchld handler");
209  }
210 
211  // Close the pipe
212  if (data->pipe_fd[0] >= 0) {
213  close(data->pipe_fd[0]);
214  data->pipe_fd[0] = -1;
215  }
216  if (data->pipe_fd[1] >= 0) {
217  close(data->pipe_fd[1]);
218  data->pipe_fd[1] = -1;
219  }
220 }
221 
222 #endif
223 
224 static gboolean
225 svc_read_output(int fd, svc_action_t * op, bool is_stderr)
226 {
227  char *data = NULL;
228  int rc = 0, len = 0;
229  char buf[500];
230  static const size_t buf_read_len = sizeof(buf) - 1;
231 
232 
233  if (fd < 0) {
234  crm_trace("No fd for %s", op->id);
235  return FALSE;
236  }
237 
238  if (is_stderr && op->stderr_data) {
239  len = strlen(op->stderr_data);
240  data = op->stderr_data;
241  crm_trace("Reading %s stderr into offset %d", op->id, len);
242 
243  } else if (is_stderr == FALSE && op->stdout_data) {
244  len = strlen(op->stdout_data);
245  data = op->stdout_data;
246  crm_trace("Reading %s stdout into offset %d", op->id, len);
247 
248  } else {
249  crm_trace("Reading %s %s into offset %d", op->id, is_stderr?"stderr":"stdout", len);
250  }
251 
252  do {
253  rc = read(fd, buf, buf_read_len);
254  if (rc > 0) {
255  buf[rc] = 0;
256  crm_trace("Got %d chars: %.80s", rc, buf);
257  data = realloc_safe(data, len + rc + 1);
258  len += sprintf(data + len, "%s", buf);
259 
260  } else if (errno != EINTR) {
261  /* error or EOF
262  * Cleanup happens in pipe_done()
263  */
264  rc = FALSE;
265  break;
266  }
267 
268  } while (rc == buf_read_len || rc < 0);
269 
270  if (is_stderr) {
271  op->stderr_data = data;
272  } else {
273  op->stdout_data = data;
274  }
275 
276  return rc;
277 }
278 
279 static int
280 dispatch_stdout(gpointer userdata)
281 {
282  svc_action_t *op = (svc_action_t *) userdata;
283 
284  return svc_read_output(op->opaque->stdout_fd, op, FALSE);
285 }
286 
287 static int
288 dispatch_stderr(gpointer userdata)
289 {
290  svc_action_t *op = (svc_action_t *) userdata;
291 
292  return svc_read_output(op->opaque->stderr_fd, op, TRUE);
293 }
294 
295 static void
296 pipe_out_done(gpointer user_data)
297 {
298  svc_action_t *op = (svc_action_t *) user_data;
299 
300  crm_trace("%p", op);
301 
302  op->opaque->stdout_gsource = NULL;
303  if (op->opaque->stdout_fd > STDOUT_FILENO) {
304  close(op->opaque->stdout_fd);
305  }
306  op->opaque->stdout_fd = -1;
307 }
308 
309 static void
310 pipe_err_done(gpointer user_data)
311 {
312  svc_action_t *op = (svc_action_t *) user_data;
313 
314  op->opaque->stderr_gsource = NULL;
315  if (op->opaque->stderr_fd > STDERR_FILENO) {
316  close(op->opaque->stderr_fd);
317  }
318  op->opaque->stderr_fd = -1;
319 }
320 
321 static struct mainloop_fd_callbacks stdout_callbacks = {
322  .dispatch = dispatch_stdout,
323  .destroy = pipe_out_done,
324 };
325 
326 static struct mainloop_fd_callbacks stderr_callbacks = {
327  .dispatch = dispatch_stderr,
328  .destroy = pipe_err_done,
329 };
330 
331 static void
332 set_ocf_env(const char *key, const char *value, gpointer user_data)
333 {
334  if (setenv(key, value, 1) != 0) {
335  crm_perror(LOG_ERR, "setenv failed for key:%s and value:%s", key, value);
336  }
337 }
338 
339 static void
340 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
341 {
342  char buffer[500];
343 
344  snprintf(buffer, sizeof(buffer), "OCF_RESKEY_%s", (char *)key);
345  set_ocf_env(buffer, value, user_data);
346 }
347 
348 static void
349 set_alert_env(gpointer key, gpointer value, gpointer user_data)
350 {
351  int rc;
352 
353  if (value != NULL) {
354  rc = setenv(key, value, 1);
355  } else {
356  rc = unsetenv(key);
357  }
358 
359  if (rc < 0) {
360  crm_perror(LOG_ERR, "setenv %s=%s",
361  (char*)key, (value? (char*)value : ""));
362  } else {
363  crm_trace("setenv %s=%s", (char*)key, (value? (char*)value : ""));
364  }
365 }
366 
373 static void
374 add_action_env_vars(const svc_action_t *op)
375 {
376  void (*env_setter)(gpointer, gpointer, gpointer) = NULL;
377  if (op->agent == NULL) {
378  env_setter = set_alert_env; /* we deal with alert handler */
379 
380  } else if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_OCF)) {
381  env_setter = set_ocf_env_with_prefix;
382  }
383 
384  if (env_setter != NULL && op->params != NULL) {
385  g_hash_table_foreach(op->params, env_setter, NULL);
386  }
387 
388  if (env_setter == NULL || env_setter == set_alert_env) {
389  return;
390  }
391 
392  set_ocf_env("OCF_RA_VERSION_MAJOR", "1", NULL);
393  set_ocf_env("OCF_RA_VERSION_MINOR", "0", NULL);
394  set_ocf_env("OCF_ROOT", OCF_ROOT_DIR, NULL);
395  set_ocf_env("OCF_EXIT_REASON_PREFIX", PCMK_OCF_REASON_PREFIX, NULL);
396 
397  if (op->rsc) {
398  set_ocf_env("OCF_RESOURCE_INSTANCE", op->rsc, NULL);
399  }
400 
401  if (op->agent != NULL) {
402  set_ocf_env("OCF_RESOURCE_TYPE", op->agent, NULL);
403  }
404 
405  /* Notes: this is not added to specification yet. Sept 10,2004 */
406  if (op->provider != NULL) {
407  set_ocf_env("OCF_RESOURCE_PROVIDER", op->provider, NULL);
408  }
409 }
410 
411 static void
412 pipe_in_single_parameter(gpointer key, gpointer value, gpointer user_data)
413 {
414  svc_action_t *op = user_data;
415  char *buffer = crm_strdup_printf("%s=%s\n", (char *)key, (char *) value);
416  int ret, total = 0, len = strlen(buffer);
417 
418  do {
419  errno = 0;
420  ret = write(op->opaque->stdin_fd, buffer + total, len - total);
421  if (ret > 0) {
422  total += ret;
423  }
424 
425  } while ((errno == EINTR) && (total < len));
426  free(buffer);
427 }
428 
435 static void
436 pipe_in_action_stdin_parameters(const svc_action_t *op)
437 {
438  crm_debug("sending args");
439  if (op->params) {
440  g_hash_table_foreach(op->params, pipe_in_single_parameter, (gpointer) op);
441  }
442 }
443 
444 gboolean
446 {
447  svc_action_t *op = data;
448 
449  crm_debug("Scheduling another invocation of %s", op->id);
450 
451  /* Clean out the old result */
452  free(op->stdout_data);
453  op->stdout_data = NULL;
454  free(op->stderr_data);
455  op->stderr_data = NULL;
456  op->opaque->repeat_timer = 0;
457 
458  services_action_async(op, NULL);
459  return FALSE;
460 }
461 
462 /* Returns FALSE if 'op' should be free'd by the caller */
463 gboolean
465 {
466  int recurring = 0;
467 
468  if (op->interval) {
469  if (op->cancel) {
472  } else {
473  recurring = 1;
474  op->opaque->repeat_timer = g_timeout_add(op->interval,
475  recurring_action_timer, (void *)op);
476  }
477  }
478 
479  if (op->opaque->callback) {
480  op->opaque->callback(op);
481  }
482 
483  op->pid = 0;
484 
486 
487  if (!recurring && op->synchronous == FALSE) {
488  /*
489  * If this is a recurring action, do not free explicitly.
490  * It will get freed whenever the action gets cancelled.
491  */
493  return TRUE;
494  }
495 
497  return FALSE;
498 }
499 
500 static void
501 operation_finished(mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode)
502 {
504  char *prefix = crm_strdup_printf("%s:%d", op->id, op->pid);
505 
507  op->status = PCMK_LRM_OP_DONE;
508  CRM_ASSERT(op->pid == pid);
509 
510  crm_trace("%s %p %p", prefix, op->opaque->stderr_gsource, op->opaque->stdout_gsource);
511  if (op->opaque->stderr_gsource) {
512  /* Make sure we have read everything from the buffer.
513  * Depending on the priority mainloop gives the fd, operation_finished
514  * could occur before all the reads are done. Force the read now.*/
515  crm_trace("%s dispatching stderr", prefix);
516  dispatch_stderr(op);
517  crm_trace("%s: %p", op->id, op->stderr_data);
519  op->opaque->stderr_gsource = NULL;
520  }
521 
522  if (op->opaque->stdout_gsource) {
523  /* Make sure we have read everything from the buffer.
524  * Depending on the priority mainloop gives the fd, operation_finished
525  * could occur before all the reads are done. Force the read now.*/
526  crm_trace("%s dispatching stdout", prefix);
527  dispatch_stdout(op);
528  crm_trace("%s: %p", op->id, op->stdout_data);
530  op->opaque->stdout_gsource = NULL;
531  }
532 
533  if (op->opaque->stdin_fd >= 0) {
534  close(op->opaque->stdin_fd);
535  }
536 
537  if (signo) {
538  if (mainloop_child_timeout(p)) {
539  crm_warn("%s - timed out after %dms", prefix, op->timeout);
541  op->rc = PCMK_OCF_TIMEOUT;
542 
543  } else if (op->cancel) {
544  /* If an in-flight recurring operation was killed because it was
545  * cancelled, don't treat that as a failure.
546  */
547  crm_info("%s - terminated with signal %d", prefix, signo);
549  op->rc = PCMK_OCF_OK;
550 
551  } else {
552  crm_warn("%s - terminated with signal %d", prefix, signo);
554  op->rc = PCMK_OCF_SIGNAL;
555  }
556 
557  } else {
558  op->rc = exitcode;
559  crm_debug("%s - exited with rc=%d", prefix, exitcode);
560  }
561 
562  free(prefix);
563  prefix = crm_strdup_printf("%s:%d:stderr", op->id, op->pid);
564  crm_log_output(LOG_NOTICE, prefix, op->stderr_data);
565 
566  free(prefix);
567  prefix = crm_strdup_printf("%s:%d:stdout", op->id, op->pid);
568  crm_log_output(LOG_DEBUG, prefix, op->stdout_data);
569 
570  free(prefix);
571  operation_finalize(op);
572 }
573 
583 static void
584 services_handle_exec_error(svc_action_t * op, int error)
585 {
586  int rc_not_installed, rc_insufficient_priv, rc_exec_error;
587 
588  /* Mimic the return codes for each standard as that's what we'll convert back from in get_uniform_rc() */
590  && safe_str_eq(op->action, "status")) {
591 
592  rc_not_installed = PCMK_LSB_STATUS_NOT_INSTALLED;
593  rc_insufficient_priv = PCMK_LSB_STATUS_INSUFFICIENT_PRIV;
594  rc_exec_error = PCMK_LSB_STATUS_UNKNOWN;
595 
596 #if SUPPORT_NAGIOS
598  rc_not_installed = NAGIOS_NOT_INSTALLED;
599  rc_insufficient_priv = NAGIOS_INSUFFICIENT_PRIV;
600  rc_exec_error = PCMK_OCF_EXEC_ERROR;
601 #endif
602 
603  } else {
604  rc_not_installed = PCMK_OCF_NOT_INSTALLED;
605  rc_insufficient_priv = PCMK_OCF_INSUFFICIENT_PRIV;
606  rc_exec_error = PCMK_OCF_EXEC_ERROR;
607  }
608 
609  switch (error) { /* see execve(2), stat(2) and fork(2) */
610  case ENOENT: /* No such file or directory */
611  case EISDIR: /* Is a directory */
612  case ENOTDIR: /* Path component is not a directory */
613  case EINVAL: /* Invalid executable format */
614  case ENOEXEC: /* Invalid executable format */
615  op->rc = rc_not_installed;
617  break;
618  case EACCES: /* permission denied (various errors) */
619  case EPERM: /* permission denied (various errors) */
620  op->rc = rc_insufficient_priv;
622  break;
623  default:
624  op->rc = rc_exec_error;
626  }
627 }
628 
629 static void
630 action_launch_child(svc_action_t *op)
631 {
632  /* SIGPIPE is ignored (which is different from signal blocking) by the gnutls library.
633  * Depending on the libqb version in use, libqb may set SIGPIPE to be ignored as well.
634  * We do not want this to be inherited by the child process. By resetting this the signal
635  * to the default behavior, we avoid some potential odd problems that occur during OCF
636  * scripts when SIGPIPE is ignored by the environment. */
637  signal(SIGPIPE, SIG_DFL);
638 
639 #if defined(HAVE_SCHED_SETSCHEDULER)
640  if (sched_getscheduler(0) != SCHED_OTHER) {
641  struct sched_param sp;
642 
643  memset(&sp, 0, sizeof(sp));
644  sp.sched_priority = 0;
645 
646  if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
647  crm_perror(LOG_ERR, "Could not reset scheduling policy to SCHED_OTHER for %s", op->id);
648  }
649  }
650 #endif
651  if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
652  crm_perror(LOG_ERR, "Could not reset process priority to 0 for %s", op->id);
653  }
654 
655  /* Man: The call setpgrp() is equivalent to setpgid(0,0)
656  * _and_ compiles on BSD variants too
657  * need to investigate if it works the same too.
658  */
659  setpgid(0, 0);
660 
662 
663 #if SUPPORT_CIBSECRETS
664  if (replace_secret_params(op->rsc, op->params) < 0) {
665  /* replacing secrets failed! */
666  if (safe_str_eq(op->action,"stop")) {
667  /* don't fail on stop! */
668  crm_info("proceeding with the stop operation for %s", op->rsc);
669 
670  } else {
671  crm_err("failed to get secrets for %s, "
672  "considering resource not configured", op->rsc);
674  }
675  }
676 #endif
677 
678  add_action_env_vars(op);
679 
680  /* Become the desired user */
681  if (op->opaque->uid && (geteuid() == 0)) {
682  if (op->opaque->gid && (setgid(op->opaque->gid) < 0)) {
683  crm_perror(LOG_ERR, "setting group to %d", op->opaque->gid);
685  }
686  if (setuid(op->opaque->uid) < 0) {
687  crm_perror(LOG_ERR, "setting user to %d", op->opaque->uid);
689  }
690  /* We could do initgroups() here if we kept a copy of the username */
691  }
692 
693  /* execute the RA */
694  execvp(op->opaque->exec, op->opaque->args);
695 
696  /* Most cases should have been already handled by stat() */
697  services_handle_exec_error(op, errno);
698 
699  _exit(op->rc);
700 }
701 
702 static void
703 action_synced_wait(svc_action_t *op, struct sigchld_data_s *data)
704 {
705  int status = 0;
706  int timeout = op->timeout;
707  time_t start = -1;
708  struct pollfd fds[3];
709  int wait_rc = 0;
710 
711  fds[0].fd = op->opaque->stdout_fd;
712  fds[0].events = POLLIN;
713  fds[0].revents = 0;
714 
715  fds[1].fd = op->opaque->stderr_fd;
716  fds[1].events = POLLIN;
717  fds[1].revents = 0;
718 
719  fds[2].fd = sigchld_open(data);
720  fds[2].events = POLLIN;
721  fds[2].revents = 0;
722 
723  crm_trace("Waiting for %d", op->pid);
724  start = time(NULL);
725  do {
726  int poll_rc = poll(fds, 3, timeout);
727 
728  if (poll_rc > 0) {
729  if (fds[0].revents & POLLIN) {
730  svc_read_output(op->opaque->stdout_fd, op, FALSE);
731  }
732 
733  if (fds[1].revents & POLLIN) {
734  svc_read_output(op->opaque->stderr_fd, op, TRUE);
735  }
736 
737  if ((fds[2].revents & POLLIN) && sigchld_received(fds[2].fd)) {
738  wait_rc = waitpid(op->pid, &status, WNOHANG);
739 
740  if (wait_rc > 0) {
741  break;
742 
743  } else if (wait_rc < 0) {
744  if (errno == ECHILD) {
745  /* Here, don't dare to kill and bail out... */
746  break;
747 
748  } else {
749  /* ...otherwise pretend process still runs. */
750  wait_rc = 0;
751  }
752  crm_perror(LOG_ERR, "waitpid() for %d failed", op->pid);
753  }
754  }
755 
756  } else if (poll_rc == 0) {
757  timeout = 0;
758  break;
759 
760  } else if (poll_rc < 0) {
761  if (errno != EINTR) {
762  crm_perror(LOG_ERR, "poll() failed");
763  break;
764  }
765  }
766 
767  timeout = op->timeout - (time(NULL) - start) * 1000;
768 
769  } while ((op->timeout < 0 || timeout > 0));
770 
771  crm_trace("Child done: %d", op->pid);
772  if (wait_rc <= 0) {
774 
775  if (op->timeout > 0 && timeout <= 0) {
777  crm_warn("%s:%d - timed out after %dms", op->id, op->pid, op->timeout);
778 
779  } else {
781  }
782 
783  /* If only child hasn't been successfully waited for, yet.
784  This is to limit killing wrong target a bit more. */
785  if (wait_rc == 0 && waitpid(op->pid, &status, WNOHANG) == 0) {
786  if (kill(op->pid, SIGKILL)) {
787  crm_err("kill(%d, KILL) failed: %d", op->pid, errno);
788  }
789  /* Safe to skip WNOHANG here as we sent non-ignorable signal. */
790  while (waitpid(op->pid, &status, 0) == (pid_t) -1 && errno == EINTR) /*omit*/;
791  }
792 
793  } else if (WIFEXITED(status)) {
794  op->status = PCMK_LRM_OP_DONE;
795  op->rc = WEXITSTATUS(status);
796  crm_info("Managed %s process %d exited with rc=%d", op->id, op->pid, op->rc);
797 
798  } else if (WIFSIGNALED(status)) {
799  int signo = WTERMSIG(status);
800 
802  crm_err("Managed %s process %d exited with signal=%d", op->id, op->pid, signo);
803  }
804 #ifdef WCOREDUMP
805  if (WCOREDUMP(status)) {
806  crm_err("Managed %s process %d dumped core", op->id, op->pid);
807  }
808 #endif
809 
810  svc_read_output(op->opaque->stdout_fd, op, FALSE);
811  svc_read_output(op->opaque->stderr_fd, op, TRUE);
812 
813  close(op->opaque->stdout_fd);
814  close(op->opaque->stderr_fd);
815  if (op->opaque->stdin_fd >= 0) {
816  close(op->opaque->stdin_fd);
817  }
818  sigchld_close(fds[2].fd);
819 }
820 
821 /* For an asynchronous 'op', returns FALSE if 'op' should be free'd by the caller */
822 /* For a synchronous 'op', returns FALSE if 'op' fails */
823 gboolean
825 {
826  int stdout_fd[2];
827  int stderr_fd[2];
828  int stdin_fd[2] = {-1, -1};
829  int rc;
830  struct stat st;
831  struct sigchld_data_s data;
832 
833  /* Fail fast */
834  if(stat(op->opaque->exec, &st) != 0) {
835  rc = errno;
836  crm_warn("Cannot execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
837  services_handle_exec_error(op, rc);
838  if (!op->synchronous) {
839  return operation_finalize(op);
840  }
841  return FALSE;
842  }
843 
844  if (pipe(stdout_fd) < 0) {
845  rc = errno;
846 
847  crm_err("pipe(stdout_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
848 
849  services_handle_exec_error(op, rc);
850  if (!op->synchronous) {
851  return operation_finalize(op);
852  }
853  return FALSE;
854  }
855 
856  if (pipe(stderr_fd) < 0) {
857  rc = errno;
858 
859  close(stdout_fd[0]);
860  close(stdout_fd[1]);
861 
862  crm_err("pipe(stderr_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
863 
864  services_handle_exec_error(op, rc);
865  if (!op->synchronous) {
866  return operation_finalize(op);
867  }
868  return FALSE;
869  }
870 
872  if (pipe(stdin_fd) < 0) {
873  rc = errno;
874 
875  close(stdout_fd[0]);
876  close(stdout_fd[1]);
877  close(stderr_fd[0]);
878  close(stderr_fd[1]);
879 
880  crm_err("pipe(stdin_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
881 
882  services_handle_exec_error(op, rc);
883  if (!op->synchronous) {
884  return operation_finalize(op);
885  }
886  return FALSE;
887  }
888  }
889 
890  if (op->synchronous) {
891  sigchld_setup(&data);
892  }
893 
894  op->pid = fork();
895  switch (op->pid) {
896  case -1:
897  rc = errno;
898 
899  close(stdout_fd[0]);
900  close(stdout_fd[1]);
901  close(stderr_fd[0]);
902  close(stderr_fd[1]);
903  if (stdin_fd[0] >= 0) {
904  close(stdin_fd[0]);
905  close(stdin_fd[1]);
906  }
907 
908  crm_err("Could not execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
909  services_handle_exec_error(op, rc);
910  if (!op->synchronous) {
911  return operation_finalize(op);
912  }
913 
914  sigchld_cleanup(&data);
915  return FALSE;
916 
917  case 0: /* Child */
918  close(stdout_fd[0]);
919  close(stderr_fd[0]);
920  if (stdin_fd[1] >= 0) {
921  close(stdin_fd[1]);
922  }
923  if (STDOUT_FILENO != stdout_fd[1]) {
924  if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
925  crm_err("dup2() failed (stdout)");
926  }
927  close(stdout_fd[1]);
928  }
929  if (STDERR_FILENO != stderr_fd[1]) {
930  if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
931  crm_err("dup2() failed (stderr)");
932  }
933  close(stderr_fd[1]);
934  }
935  if ((stdin_fd[0] >= 0) &&
936  (STDIN_FILENO != stdin_fd[0])) {
937  if (dup2(stdin_fd[0], STDIN_FILENO) != STDIN_FILENO) {
938  crm_err("dup2() failed (stdin)");
939  }
940  close(stdin_fd[0]);
941  }
942 
943  if (op->synchronous) {
944  sigchld_cleanup(&data);
945  }
946 
947  action_launch_child(op);
948  CRM_ASSERT(0); /* action_launch_child is effectively noreturn */
949  }
950 
951  /* Only the parent reaches here */
952  close(stdout_fd[1]);
953  close(stderr_fd[1]);
954  if (stdin_fd[0] >= 0) {
955  close(stdin_fd[0]);
956  }
957 
958  op->opaque->stdout_fd = stdout_fd[0];
960  if (rc < 0) {
961  crm_warn("Could not set child output non-blocking: %s "
962  CRM_XS " rc=%d",
963  pcmk_strerror(rc), rc);
964  }
965 
966  op->opaque->stderr_fd = stderr_fd[0];
968  if (rc < 0) {
969  crm_warn("Could not set child error output non-blocking: %s "
970  CRM_XS " rc=%d",
971  pcmk_strerror(rc), rc);
972  }
973 
974  op->opaque->stdin_fd = stdin_fd[1];
975  if (op->opaque->stdin_fd >= 0) {
976  // using buffer behind non-blocking-fd here - that could be improved
977  // as long as no other standard uses stdin_fd assume stonith
979  if (rc < 0) {
980  crm_warn("Could not set child input non-blocking: %s "
981  CRM_XS " fd=%d,rc=%d",
982  pcmk_strerror(rc), op->opaque->stdin_fd, rc);
983  }
984  pipe_in_action_stdin_parameters(op);
985  // as long as we are handling parameters directly in here just close
986  close(op->opaque->stdin_fd);
987  op->opaque->stdin_fd = -1;
988  }
989 
990  // after fds are setup properly and before we plug anything into mainloop
991  if (op->opaque->fork_callback) {
992  op->opaque->fork_callback(op);
993  }
994 
995  if (op->synchronous) {
996  action_synced_wait(op, &data);
997  sigchld_cleanup(&data);
998  } else {
999 
1000  crm_trace("Async waiting for %d - %s", op->pid, op->opaque->exec);
1002  op->timeout,
1003  op->id,
1004  op,
1006  operation_finished);
1007 
1008 
1010  G_PRIORITY_LOW,
1011  op->opaque->stdout_fd, op, &stdout_callbacks);
1012 
1014  G_PRIORITY_LOW,
1015  op->opaque->stderr_fd, op, &stderr_callbacks);
1016 
1018  }
1019 
1020  return TRUE;
1021 }
1022 
1023 GList *
1024 services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
1025 {
1026  GList *list = NULL;
1027  struct dirent **namelist;
1028  int entries = 0, lpc = 0;
1029  char buffer[PATH_MAX];
1030 
1031  entries = scandir(root, &namelist, NULL, alphasort);
1032  if (entries <= 0) {
1033  return list;
1034  }
1035 
1036  for (lpc = 0; lpc < entries; lpc++) {
1037  struct stat sb;
1038 
1039  if ('.' == namelist[lpc]->d_name[0]) {
1040  free(namelist[lpc]);
1041  continue;
1042  }
1043 
1044  snprintf(buffer, sizeof(buffer), "%s/%s", root, namelist[lpc]->d_name);
1045 
1046  if (stat(buffer, &sb)) {
1047  continue;
1048  }
1049 
1050  if (S_ISDIR(sb.st_mode)) {
1051  if (files) {
1052  free(namelist[lpc]);
1053  continue;
1054  }
1055 
1056  } else if (S_ISREG(sb.st_mode)) {
1057  if (files == FALSE) {
1058  free(namelist[lpc]);
1059  continue;
1060 
1061  } else if (executable
1062  && (sb.st_mode & S_IXUSR) == 0
1063  && (sb.st_mode & S_IXGRP) == 0 && (sb.st_mode & S_IXOTH) == 0) {
1064  free(namelist[lpc]);
1065  continue;
1066  }
1067  }
1068 
1069  list = g_list_append(list, strdup(namelist[lpc]->d_name));
1070 
1071  free(namelist[lpc]);
1072  }
1073 
1074  free(namelist);
1075  return list;
1076 }
1077 
1078 GList *
1080 {
1081  return get_directory_list(LSB_ROOT_DIR, TRUE, TRUE);
1082 }
1083 
1084 GList *
1086 {
1087  return get_directory_list(OCF_ROOT_DIR "/resource.d", FALSE, TRUE);
1088 }
1089 
1090 GList *
1091 resources_os_list_ocf_agents(const char *provider)
1092 {
1093  GList *gIter = NULL;
1094  GList *result = NULL;
1095  GList *providers = NULL;
1096 
1097  if (provider) {
1098  char buffer[500];
1099 
1100  snprintf(buffer, sizeof(buffer), "%s/resource.d/%s", OCF_ROOT_DIR, provider);
1101  return get_directory_list(buffer, TRUE, TRUE);
1102  }
1103 
1104  providers = resources_os_list_ocf_providers();
1105  for (gIter = providers; gIter != NULL; gIter = gIter->next) {
1106  GList *tmp1 = result;
1107  GList *tmp2 = resources_os_list_ocf_agents(gIter->data);
1108 
1109  if (tmp2) {
1110  result = g_list_concat(tmp1, tmp2);
1111  }
1112  }
1113  g_list_free_full(providers, free);
1114  return result;
1115 }
1116 
1117 #if SUPPORT_NAGIOS
1118 GList *
1120 {
1121  GList *plugin_list = NULL;
1122  GList *result = NULL;
1123  GList *gIter = NULL;
1124 
1125  plugin_list = get_directory_list(NAGIOS_PLUGIN_DIR, TRUE, TRUE);
1126 
1127  /* Make sure both the plugin and its metadata exist */
1128  for (gIter = plugin_list; gIter != NULL; gIter = gIter->next) {
1129  const char *plugin = gIter->data;
1130  char *metadata = crm_strdup_printf(NAGIOS_METADATA_DIR "/%s.xml", plugin);
1131  struct stat st;
1132 
1133  if (stat(metadata, &st) == 0) {
1134  result = g_list_append(result, strdup(plugin));
1135  }
1136 
1137  free(metadata);
1138  }
1139  g_list_free_full(plugin_list, free);
1140  return result;
1141 }
1142 #endif
Services API.
#define LOG_TRACE
Definition: logging.h:29
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:190
void(* callback)(svc_action_t *op)
A dumping ground.
void services_action_free(svc_action_t *op)
Definition: services.c:540
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
Definition: mainloop.c:886
char * standard
Definition: services.h:169
#define crm_log_output(level, prefix, output)
Definition: logging.h:92
const char * pcmk_strerror(int rc)
Definition: logging.c:1017
char * id
Definition: services.h:164
mainloop_io_t * stderr_gsource
GList * resources_os_list_ocf_agents(const char *provider)
GList * resources_os_list_ocf_providers(void)
int alphasort(const void *dirent1, const void *dirent2)
gboolean recurring_action_timer(gpointer data)
void pcmk__close_fds_in_child(bool)
Definition: io.c:534
void mainloop_child_add_with_flags(pid_t pid, int timeout, const char *desc, void *userdata, enum mainloop_child_flags, void(*callback)(mainloop_child_t *p, pid_t pid, int core, int signo, int exitcode))
Definition: mainloop.c:1173
struct mainloop_child_s mainloop_child_t
Definition: mainloop.h:26
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
char * rsc
Definition: services.h:165
int interval
Definition: services.h:167
gboolean services_os_action_execute(svc_action_t *op)
G_GNUC_INTERNAL GList * resources_os_list_nagios_agents(void)
uint32_t pid
Definition: internal.h:77
Wrappers for and extensions to glib mainloop.
GList * resources_os_list_lsb_agents(void)
void services_action_cleanup(svc_action_t *op)
Definition: services.c:501
int(* dispatch)(gpointer userdata)
Definition: mainloop.h:104
volatile struct sigchld_data_s * last_sigchld_data
enum svc_action_flags flags
Definition: services.h:186
#define crm_warn(fmt, args...)
Definition: logging.h:275
#define PCMK_RESOURCE_CLASS_OCF
Definition: services.h:57
gboolean cancel_recurring_action(svc_action_t *op)
Definition: services.c:592
svc_action_private_t * opaque
Definition: services.h:199
#define OCF_ROOT_DIR
Definition: services.h:39
#define crm_debug(fmt, args...)
Definition: logging.h:279
void * mainloop_child_userdata(mainloop_child_t *child)
Definition: mainloop.c:964
gboolean operation_finalize(svc_action_t *op)
char * stdout_data
Definition: services.h:189
GHashTable * params
Definition: services.h:174
#define crm_trace(fmt, args...)
Definition: logging.h:280
int setenv(const char *name, const char *value, int why)
int crm_set_nonblocking(int fd)
Definition: io.c:510
char * agent
Definition: services.h:171
int synchronous
Definition: services.h:185
#define LSB_ROOT_DIR
Definition: services.h:43
#define PCMK_OCF_REASON_PREFIX
Definition: services.h:70
#define PCMK_RESOURCE_CLASS_STONITH
Definition: services.h:64
#define CRM_XS
Definition: logging.h:42
char * args[MAX_ARGC]
void services_add_inflight_op(svc_action_t *op)
Definition: services.c:776
void services_untrack_op(svc_action_t *op)
Definition: services.c:797
int replace_secret_params(const char *rsc_id, GHashTable *params)
Definition: cib_secrets.c:91
char * action
Definition: services.h:166
#define PCMK_RESOURCE_CLASS_NAGIOS
Definition: services.h:63
#define PCMK_RESOURCE_CLASS_LSB
Definition: services.h:59
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:252
#define NAGIOS_PLUGIN_DIR
Definition: config.h:624
#define crm_err(fmt, args...)
Definition: logging.h:274
void mainloop_clear_child_userdata(mainloop_child_t *child)
Definition: mainloop.c:970
GList * get_directory_list(const char *root, gboolean files, gboolean executable)
Get a list of files or directories in a given path.
Definition: services.c:1344
mainloop_io_t * stdout_gsource
#define CRM_ASSERT(expr)
Definition: error.h:20
char data[0]
Definition: internal.h:86
void mainloop_del_fd(mainloop_io_t *client)
Definition: mainloop.c:930
#define safe_str_eq(a, b)
Definition: util.h:74
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
Definition: services.c:840
char * provider
Definition: services.h:170
void(* fork_callback)(svc_action_t *op)
#define crm_info(fmt, args...)
Definition: logging.h:277
#define NAGIOS_METADATA_DIR
Definition: config.h:621
int mainloop_child_timeout(mainloop_child_t *child)
Definition: mainloop.c:958
char * stderr_data
Definition: services.h:188