16 #include <sys/types.h>    25 #include <sys/resource.h>    33 static void close_pipe(
int fildes[]);
    43 #ifdef HAVE_SYS_SIGNALFD_H    47 #include <sys/signalfd.h>    50 struct sigchld_data_s {
    57 sigchld_setup(
struct sigchld_data_s *
data)
    59     sigemptyset(&(
data->mask));
    60     sigaddset(&(
data->mask), SIGCHLD);
    62     sigemptyset(&(
data->old_mask));
    65     if (sigprocmask(SIG_BLOCK, &(
data->mask), &(
data->old_mask)) < 0) {
    66         crm_err(
"Wait for child process completion failed: %s "    75 sigchld_open(
struct sigchld_data_s *
data)
    81     fd = signalfd(-1, &(
data->mask), SFD_NONBLOCK);
    83         crm_err(
"Wait for child process completion failed: %s "   100 sigchld_received(
int fd)
   102     struct signalfd_siginfo fdsi;
   108     s = read(fd, &fdsi, 
sizeof(
struct signalfd_siginfo));
   109     if (s != 
sizeof(
struct signalfd_siginfo)) {
   110         crm_err(
"Wait for child process completion failed: %s "   113     } 
else if (fdsi.ssi_signo == SIGCHLD) {
   121 sigchld_cleanup(
struct sigchld_data_s *
data)
   124     if ((sigismember(&(
data->old_mask), SIGCHLD) == 0)
   125         && (sigprocmask(SIG_UNBLOCK, &(
data->mask), NULL) < 0)) {
   126         crm_warn(
"Could not clean up after child process completion: %s",
   131 #else // HAVE_SYS_SIGNALFD_H not defined   135 struct sigchld_data_s {
   138     struct sigaction old_sa;    
   151         crm_err(
"Wait for child process completion failed: %s "   157 sigchld_setup(
struct sigchld_data_s *
data)
   161     data->pipe_fd[0] = 
data->pipe_fd[1] = -1;
   163     if (pipe(
data->pipe_fd) == -1) {
   164         crm_err(
"Wait for child process completion failed: %s "   171         crm_warn(
"Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
   176         crm_warn(
"Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
   181     data->sa.sa_handler = sigchld_handler;
   182     data->sa.sa_flags = 0;
   183     sigemptyset(&(
data->sa.sa_mask));
   184     if (sigaction(SIGCHLD, &(
data->sa), &(
data->old_sa)) < 0) {
   185         crm_err(
"Wait for child process completion failed: %s "   195 sigchld_open(
struct sigchld_data_s *
data)
   198     return data->pipe_fd[0];
   202 sigchld_close(
int fd)
   209 sigchld_received(
int fd)
   218     while (read(fd, &ch, 1) == 1) ;
   223 sigchld_cleanup(
struct sigchld_data_s *
data)
   226     if (sigaction(SIGCHLD, &(
data->old_sa), NULL) < 0) {
   227         crm_warn(
"Could not clean up after child process completion: %s",
   231     close_pipe(
data->pipe_fd);
   243 close_pipe(
int fildes[])
   245     if (fildes[0] >= 0) {
   249     if (fildes[1] >= 0) {
   256 svc_read_output(
int fd, 
svc_action_t * op, 
bool is_stderr)
   261     static const size_t buf_read_len = 
sizeof(buf) - 1;
   272         crm_trace(
"Reading %s stderr into offset %d", op->
id, len);
   274     } 
else if (is_stderr == FALSE && op->
stdout_data) {
   277         crm_trace(
"Reading %s stdout into offset %d", op->
id, len);
   280         crm_trace(
"Reading %s %s into offset %d", op->
id, is_stderr?
"stderr":
"stdout", len);
   284         rc = read(fd, buf, buf_read_len);
   289             len += sprintf(
data + len, 
"%s", buf);
   291         } 
else if (errno != EINTR) {
   299     } 
while (
rc == buf_read_len || 
rc < 0);
   311 dispatch_stdout(gpointer userdata)
   319 dispatch_stderr(gpointer userdata)
   327 pipe_out_done(gpointer user_data)
   341 pipe_err_done(gpointer user_data)
   354     .destroy = pipe_out_done,
   359     .destroy = pipe_err_done,
   363 set_ocf_env(
const char *key, 
const char *value, gpointer user_data)
   365     if (
setenv(key, value, 1) != 0) {
   366         crm_perror(LOG_ERR, 
"setenv failed for key:%s and value:%s", key, value);
   371 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
   375     snprintf(buffer, 
sizeof(buffer), strcmp(key, 
"OCF_CHECK_LEVEL") != 0 ? 
"OCF_RESKEY_%s" : 
"%s", (
char *)key);
   376     set_ocf_env(buffer, value, user_data);
   380 set_alert_env(gpointer key, gpointer value, gpointer user_data)
   392                   (
char*)key, (value? (
char*)value : 
""));
   394         crm_trace(
"setenv %s=%s", (
char*)key, (value? (
char*)value : 
""));
   407     void (*env_setter)(gpointer, gpointer, gpointer) = NULL;
   408     if (op->
agent == NULL) {
   409         env_setter = set_alert_env;  
   412         env_setter = set_ocf_env_with_prefix;
   415     if (env_setter != NULL && op->
params != NULL) {
   416         g_hash_table_foreach(op->
params, env_setter, NULL);
   419     if (env_setter == NULL || env_setter == set_alert_env) {
   423     set_ocf_env(
"OCF_RA_VERSION_MAJOR", 
"1", NULL);
   424     set_ocf_env(
"OCF_RA_VERSION_MINOR", 
"0", NULL);
   429         set_ocf_env(
"OCF_RESOURCE_INSTANCE", op->
rsc, NULL);
   432     if (op->
agent != NULL) {
   433         set_ocf_env(
"OCF_RESOURCE_TYPE", op->
agent, NULL);
   438         set_ocf_env(
"OCF_RESOURCE_PROVIDER", op->
provider, NULL);
   443 pipe_in_single_parameter(gpointer key, gpointer value, gpointer user_data)
   447     int ret, total = 0, len = strlen(buffer);
   456     } 
while ((errno == EINTR) && (total < len));
   471         g_hash_table_foreach(op->
params, pipe_in_single_parameter, (gpointer) op);
   480     crm_debug(
"Scheduling another invocation of %s", op->
id);
   555                   op->
id, op->
pid, (is_stderr? 
"stdout" : 
"stderr"));
   556         svc_read_output(fd, op, is_stderr);
   573     strcpy(prefix + strlen(prefix) - strlen(
"error output"), 
"output");
   590     finish_op_output(op, 
true);
   591     finish_op_output(op, 
false);
   596         crm_debug(
"%s[%d] exited with status %d", op->
id, op->
pid, exitcode);
   610                  op->
id, op->
pid, strsignal(signo), signo);
   616                  op->
id, op->
pid, strsignal(signo), signo);
   635 services_handle_exec_error(
svc_action_t * op, 
int error)
   637     int rc_not_installed, rc_insufficient_priv, rc_exec_error;
   666             op->
rc = rc_not_installed;
   671             op->
rc = rc_insufficient_priv;
   675             op->
rc = rc_exec_error;
   688     signal(SIGPIPE, SIG_DFL);
   690 #if defined(HAVE_SCHED_SETSCHEDULER)   691     if (sched_getscheduler(0) != SCHED_OTHER) {
   692         struct sched_param sp;
   694         memset(&sp, 0, 
sizeof(sp));
   695         sp.sched_priority = 0;
   697         if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
   698             crm_perror(LOG_ERR, 
"Could not reset scheduling policy to SCHED_OTHER for %s", op->
id);
   702     if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
   703         crm_perror(LOG_ERR, 
"Could not reset process priority to 0 for %s", op->
id);
   714 #if SUPPORT_CIBSECRETS   719             crm_info(
"proceeding with the stop operation for %s", op->
rsc);
   722             crm_err(
"failed to get secrets for %s, "   723                     "considering resource not configured", op->
rsc);
   729     add_action_env_vars(op);
   732     if (op->
opaque->
uid && (geteuid() == 0)) {
   742         if (setgroups(0, NULL) < 0) {
   743             crm_perror(LOG_ERR, 
"Could not set child groups");
   758     services_handle_exec_error(op, errno);
   769     struct pollfd fds[3];
   773     fds[0].events = POLLIN;
   777     fds[1].events = POLLIN;
   780     fds[2].fd = sigchld_open(
data);
   781     fds[2].events = POLLIN;
   787         int poll_rc = poll(fds, 3, 
timeout);
   790             if (fds[0].revents & POLLIN) {
   794             if (fds[1].revents & POLLIN) {
   798             if ((fds[2].revents & POLLIN) && sigchld_received(fds[2].fd)) {
   799                 wait_rc = waitpid(op->
pid, &status, WNOHANG);
   801                 if ((wait_rc > 0) || ((wait_rc < 0) && (errno == ECHILD))) {
   805                 } 
else if (wait_rc < 0) {
   806                     crm_warn(
"Wait for completion of %s[%d] failed: %s "   813         } 
else if (poll_rc == 0) {
   818         } 
else if ((poll_rc < 0) && (errno != EINTR)) {
   819             crm_err(
"Wait for completion of %s[%d] failed: %s "   835             crm_warn(
"%s[%d] timed out after %dms",
   844         if (wait_rc == 0 && waitpid(op->
pid, &status, WNOHANG) == 0) {
   845             if (kill(op->
pid, SIGKILL)) {
   846                 crm_warn(
"Could not kill rogue child %s[%d]: %s",
   850             while (waitpid(op->
pid, &status, 0) == (pid_t) -1 && errno == EINTR) ;
   853     } 
else if (WIFEXITED(status)) {
   855         op->
rc = WEXITSTATUS(status);
   858     } 
else if (WIFSIGNALED(status)) {
   859         int signo = WTERMSIG(status);
   863                 op->
id, op->
pid, strsignal(signo), signo);
   866     if (WCOREDUMP(status)) {
   871     finish_op_output(op, 
true);
   872     finish_op_output(op, 
false);
   874     sigchld_close(fds[2].fd);
   884     int stdin_fd[2] = {-1, -1};
   887     struct sigchld_data_s 
data;
   894         services_handle_exec_error(op, 
rc);
   901     if (pipe(stdout_fd) < 0) {
   903         crm_err(
"Cannot execute '%s': %s " CRM_XS " pipe(stdout) rc=%d",
   905         services_handle_exec_error(op, 
rc);
   912     if (pipe(stderr_fd) < 0) {
   915         close_pipe(stdout_fd);
   917         crm_err(
"Cannot execute '%s': %s " CRM_XS " pipe(stderr) rc=%d",
   919         services_handle_exec_error(op, 
rc);
   927         if (pipe(stdin_fd) < 0) {
   930             close_pipe(stdout_fd);
   931             close_pipe(stderr_fd);
   933             crm_err(
"Cannot execute '%s': %s " CRM_XS " pipe(stdin) rc=%d",
   935             services_handle_exec_error(op, 
rc);
   944         close_pipe(stdin_fd);
   945         close_pipe(stdout_fd);
   946         close_pipe(stderr_fd);
   947         sigchld_cleanup(&
data);
   955             close_pipe(stdin_fd);
   956             close_pipe(stdout_fd);
   957             close_pipe(stderr_fd);
   961             services_handle_exec_error(op, 
rc);
   966             sigchld_cleanup(&
data);
   972             if (stdin_fd[1] >= 0) {
   975             if (STDOUT_FILENO != stdout_fd[1]) {
   976                 if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
   977                     crm_warn(
"Can't redirect output from '%s': %s "   983             if (STDERR_FILENO != stderr_fd[1]) {
   984                 if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
   985                     crm_warn(
"Can't redirect error output from '%s': %s "   991             if ((stdin_fd[0] >= 0) &&
   992                 (STDIN_FILENO != stdin_fd[0])) {
   993                 if (dup2(stdin_fd[0], STDIN_FILENO) != STDIN_FILENO) {
   994                     crm_warn(
"Can't redirect input to '%s': %s "  1002                 sigchld_cleanup(&
data);
  1005             action_launch_child(op);
  1010     close(stdout_fd[1]);
  1011     close(stderr_fd[1]);
  1012     if (stdin_fd[0] >= 0) {
  1019         crm_warn(
"Could not set '%s' output non-blocking: %s "  1027         crm_warn(
"Could not set '%s' error output non-blocking: %s "  1038             crm_warn(
"Could not set '%s' input non-blocking: %s "  1042         pipe_in_action_stdin_parameters(op);
  1054         action_synced_wait(op, &
data);
  1055         sigchld_cleanup(&
data);
  1063                                       operation_finished);
  1084     struct dirent **namelist;
  1085     int entries = 0, lpc = 0;
  1086     char buffer[PATH_MAX];
  1088     entries = scandir(root, &namelist, NULL, 
alphasort);
  1093     for (lpc = 0; lpc < entries; lpc++) {
  1096         if (
'.' == namelist[lpc]->d_name[0]) {
  1097             free(namelist[lpc]);
  1101         snprintf(buffer, 
sizeof(buffer), 
"%s/%s", root, namelist[lpc]->d_name);
  1103         if (stat(buffer, &sb)) {
  1107         if (S_ISDIR(sb.st_mode)) {
  1109                 free(namelist[lpc]);
  1113         } 
else if (S_ISREG(sb.st_mode)) {
  1114             if (files == FALSE) {
  1115                 free(namelist[lpc]);
  1118             } 
else if (executable
  1119                        && (sb.st_mode & S_IXUSR) == 0
  1120                        && (sb.st_mode & S_IXGRP) == 0 && (sb.st_mode & S_IXOTH) == 0) {
  1121                 free(namelist[lpc]);
  1126         list = g_list_append(list, strdup(namelist[lpc]->d_name));
  1128         free(namelist[lpc]);
  1144     GList *gIter = NULL;
  1145     GList *result = NULL;
  1146     GList *providers = NULL;
  1151         snprintf(buffer, 
sizeof(buffer), 
"%s/resource.d/%s", 
OCF_ROOT_DIR, provider);
  1156     for (gIter = providers; gIter != NULL; gIter = gIter->next) {
  1157         GList *tmp1 = result;
  1161             result = g_list_concat(tmp1, tmp2);
  1164     g_list_free_full(providers, free);
  1172     gboolean 
rc = FALSE;
  1175     if (provider == NULL || agent == NULL) {
  1180     if (stat(buf, &
st) == 0) {
 
#define CRM_CHECK(expr, failure_action)
 
void(* callback)(svc_action_t *op)
 
const char * pcmk_strerror(int rc)
 
void services_action_free(svc_action_t *op)
 
gboolean services__ocf_agent_exists(const char *provider, const char *agent)
 
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
 
#define crm_log_output(level, prefix, output)
 
mainloop_io_t * stderr_gsource
 
GList * resources_os_list_ocf_agents(const char *provider)
 
GList * resources_os_list_ocf_providers(void)
 
int pcmk__substitute_secrets(const char *rsc_id, GHashTable *params)
 
int alphasort(const void *dirent1, const void *dirent2)
 
gboolean recurring_action_timer(gpointer data)
 
struct mainloop_io_s mainloop_io_t
 
void pcmk__close_fds_in_child(bool)
 
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))
 
struct mainloop_child_s mainloop_child_t
 
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
 
gboolean services_os_action_execute(svc_action_t *op)
 
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
 
Wrappers for and extensions to glib mainloop.
 
void services_action_cleanup(svc_action_t *op)
 
int(* dispatch)(gpointer userdata)
 
volatile struct sigchld_data_s * last_sigchld_data
 
enum svc_action_flags flags
 
#define crm_warn(fmt, args...)
 
#define PCMK_RESOURCE_CLASS_OCF
 
gboolean cancel_recurring_action(svc_action_t *op)
 
svc_action_private_t * opaque
 
#define crm_debug(fmt, args...)
 
void * mainloop_child_userdata(mainloop_child_t *child)
 
gboolean operation_finalize(svc_action_t *op)
 
#define crm_trace(fmt, args...)
 
int setenv(const char *name, const char *value, int why)
 
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
 
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
 
#define PCMK_OCF_REASON_PREFIX
 
void services_add_inflight_op(svc_action_t *op)
 
void services_untrack_op(svc_action_t *op)
 
#define PCMK_RESOURCE_CLASS_NAGIOS
 
#define PCMK_RESOURCE_CLASS_LSB
 
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
 
#define crm_err(fmt, args...)
 
void mainloop_clear_child_userdata(mainloop_child_t *child)
 
GList * get_directory_list(const char *root, gboolean files, gboolean executable)
Get a list of files or directories in a given path.
 
mainloop_io_t * stdout_gsource
 
void mainloop_del_fd(mainloop_io_t *client)
 
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
 
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
 
void(* fork_callback)(svc_action_t *op)
 
#define crm_info(fmt, args...)
 
int pcmk__set_nonblocking(int fd)
 
int mainloop_child_timeout(mainloop_child_t *child)