14 #include <sys/types.h> 
   22 #include <sys/resource.h> 
   24 #ifdef HAVE_SYS_SIGNALFD_H 
   25 #include <sys/signalfd.h> 
   34 #if SUPPORT_CIBSECRETS 
   39 svc_read_output(
int fd, 
svc_action_t * op, 
bool is_stderr)
 
   44     static const size_t buf_read_len = 
sizeof(buf) - 1;
 
   55         crm_trace(
"Reading %s stderr into offset %d", op->
id, len);
 
   60         crm_trace(
"Reading %s stdout into offset %d", op->
id, len);
 
   63         crm_trace(
"Reading %s %s into offset %d", op->
id, is_stderr?
"stderr":
"stdout", len);
 
   67         rc = read(fd, buf, buf_read_len);
 
   69             crm_trace(
"Got %d chars: %.80s", rc, buf);
 
   71             data = realloc_safe(data, len + rc + 1);
 
   72             len += sprintf(data + len, 
"%s", buf);
 
   74         } 
else if (errno != EINTR) {
 
   82     } 
while (rc == buf_read_len || rc < 0);
 
   94 dispatch_stdout(gpointer userdata)
 
  102 dispatch_stderr(gpointer userdata)
 
  110 pipe_out_done(gpointer user_data)
 
  124 pipe_err_done(gpointer user_data)
 
  137     .destroy = pipe_out_done,
 
  142     .destroy = pipe_err_done,
 
  146 set_ocf_env(
const char *key, 
const char *value, gpointer user_data)
 
  148     if (
setenv(key, value, 1) != 0) {
 
  149         crm_perror(LOG_ERR, 
"setenv failed for key:%s and value:%s", key, value);
 
  154 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
 
  158     snprintf(buffer, 
sizeof(buffer), 
"OCF_RESKEY_%s", (
char *)key);
 
  159     set_ocf_env(buffer, value, user_data);
 
  176         g_hash_table_foreach(op->
params, set_ocf_env_with_prefix, NULL);
 
  179     set_ocf_env(
"OCF_RA_VERSION_MAJOR", 
"1", NULL);
 
  180     set_ocf_env(
"OCF_RA_VERSION_MINOR", 
"0", NULL);
 
  185         set_ocf_env(
"OCF_RESOURCE_INSTANCE", op->
rsc, NULL);
 
  188     if (op->
agent != NULL) {
 
  189         set_ocf_env(
"OCF_RESOURCE_TYPE", op->
agent, NULL);
 
  194         set_ocf_env(
"OCF_RESOURCE_PROVIDER", op->
provider, NULL);
 
  203     crm_debug(
"Scheduling another invocation of %s", op->
id);
 
  269         crm_trace(
"%s dispatching stderr", prefix);
 
  280         crm_trace(
"%s dispatching stdout", prefix);
 
  295                                 "%s - terminated with signal %d", prefix, signo);
 
  302         crm_debug(
"%s - exited with rc=%d", prefix, exitcode);
 
  327 services_handle_exec_error(
svc_action_t * op, 
int error)
 
  329     int rc_not_installed, rc_insufficient_priv, rc_exec_error;
 
  358             op->
rc = rc_not_installed;
 
  363             op->
rc = rc_insufficient_priv;
 
  367             op->
rc = rc_exec_error;
 
  382     signal(SIGPIPE, SIG_DFL);
 
  384 #if defined(HAVE_SCHED_SETSCHEDULER) 
  385     if (sched_getscheduler(0) != SCHED_OTHER) {
 
  386         struct sched_param sp;
 
  388         memset(&sp, 0, 
sizeof(sp));
 
  389         sp.sched_priority = 0;
 
  391         if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
 
  392             crm_perror(LOG_ERR, 
"Could not reset scheduling policy to SCHED_OTHER for %s", op->
id);
 
  396     if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
 
  397         crm_perror(LOG_ERR, 
"Could not reset process priority to 0 for %s", op->
id);
 
  407     for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) {
 
  411 #if SUPPORT_CIBSECRETS 
  416             crm_info(
"proceeding with the stop operation for %s", op->
rsc);
 
  419             crm_err(
"failed to get secrets for %s, " 
  420                     "considering resource not configured", op->
rsc);
 
  426     add_action_env_vars(op);
 
  429     if (op->
opaque->
uid && (geteuid() == 0)) {
 
  445     services_handle_exec_error(op, errno);
 
  450 #ifndef HAVE_SYS_SIGNALFD_H 
  451 static int sigchld_pipe[2] = { -1, -1 };
 
  456     if ((sigchld_pipe[1] >= 0) && (write(sigchld_pipe[1], 
"", 1) == -1)) {
 
  469     struct pollfd fds[3];
 
  472 #ifdef HAVE_SYS_SIGNALFD_H 
  473     sfd = signalfd(-1, mask, SFD_NONBLOCK);
 
  478     sfd = sigchld_pipe[0];
 
  482     fds[0].events = POLLIN;
 
  486     fds[1].events = POLLIN;
 
  490     fds[2].events = POLLIN;
 
  496         int poll_rc = poll(fds, 3, timeout);
 
  499             if (fds[0].revents & POLLIN) {
 
  503             if (fds[1].revents & POLLIN) {
 
  507             if (fds[2].revents & POLLIN) {
 
  508 #ifdef HAVE_SYS_SIGNALFD_H 
  509                 struct signalfd_siginfo fdsi;
 
  512                 s = read(sfd, &fdsi, 
sizeof(
struct signalfd_siginfo));
 
  513                 if (s != 
sizeof(
struct signalfd_siginfo)) {
 
  514                     crm_perror(LOG_ERR, 
"Read from signal fd %d failed", sfd);
 
  516                 } 
else if (fdsi.ssi_signo == SIGCHLD) {
 
  521                     while (read(sfd, &ch, 1) == 1) ;
 
  523                     wait_rc = waitpid(op->
pid, &status, WNOHANG);
 
  528                     } 
else if (wait_rc < 0){
 
  529                         if (errno == ECHILD) {
 
  542         } 
else if (poll_rc == 0) {
 
  546         } 
else if (poll_rc < 0) {
 
  547             if (errno != EINTR) {
 
  553         timeout = op->
timeout - (time(NULL) - start) * 1000;
 
  555     } 
while ((op->
timeout < 0 || timeout > 0));
 
  561         if (op->
timeout > 0 && timeout <= 0) {
 
  571         if (wait_rc == 0 && waitpid(op->
pid, &status, WNOHANG) == 0) {
 
  572             if (kill(op->
pid, SIGKILL)) {
 
  573                 crm_err(
"kill(%d, KILL) failed: %d", op->
pid, errno);
 
  576             while (waitpid(op->
pid, &status, 0) == (pid_t) -1 && errno == EINTR) ;
 
  579     } 
else if (WIFEXITED(status)) {
 
  581         op->
rc = WEXITSTATUS(status);
 
  582         crm_info(
"Managed %s process %d exited with rc=%d", op->
id, op->
pid, op->
rc);
 
  584     } 
else if (WIFSIGNALED(status)) {
 
  585         int signo = WTERMSIG(status);
 
  588         crm_err(
"Managed %s process %d exited with signal=%d", op->
id, op->
pid, signo);
 
  591     if (WCOREDUMP(status)) {
 
  592         crm_err(
"Managed %s process %d dumped core", op->
id, op->
pid);
 
  602 #ifdef HAVE_SYS_SIGNALFD_H 
  618 #ifdef HAVE_SYS_SIGNALFD_H 
  621 #define sigchld_cleanup() do {                                                \ 
  622     if (sigismember(&old_mask, SIGCHLD) == 0) {                               \ 
  623         if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) {                      \ 
  624             crm_perror(LOG_ERR, "sigprocmask() failed to unblock sigchld");   \ 
  630     struct sigaction old_sa;
 
  631 #define sigchld_cleanup() do {                                                \ 
  632     if (sigaction(SIGCHLD, &old_sa, NULL) < 0) {                              \ 
  633         crm_perror(LOG_ERR, "sigaction() failed to remove sigchld handler");  \ 
  635     close(sigchld_pipe[0]);                                                   \ 
  636     close(sigchld_pipe[1]);                                                   \ 
  637     sigchld_pipe[0] = sigchld_pipe[1] = -1;                                   \ 
  645         services_handle_exec_error(op, rc);
 
  652     if (pipe(stdout_fd) < 0) {
 
  657         services_handle_exec_error(op, rc);
 
  664     if (pipe(stderr_fd) < 0) {
 
  672         services_handle_exec_error(op, rc);
 
  680 #ifdef HAVE_SYS_SIGNALFD_H 
  682         sigaddset(&mask, SIGCHLD);
 
  683         sigemptyset(&old_mask);
 
  685         if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) {
 
  686             crm_perror(LOG_ERR, 
"sigprocmask() failed to block sigchld");
 
  691         if(pipe(sigchld_pipe) == -1) {
 
  697             crm_warn(
"Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
 
  702             crm_warn(
"Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
 
  706         sa.sa_handler = sigchld_handler;
 
  708         sigemptyset(&sa.sa_mask);
 
  709         if (sigaction(SIGCHLD, &sa, &old_sa) < 0) {
 
  710             crm_perror(LOG_ERR, 
"sigaction() failed to set sigchld handler");
 
  728             services_handle_exec_error(op, rc);
 
  739             if (STDOUT_FILENO != stdout_fd[1]) {
 
  740                 if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
 
  741                     crm_err(
"dup2() failed (stdout)");
 
  745             if (STDERR_FILENO != stderr_fd[1]) {
 
  746                 if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
 
  747                     crm_err(
"dup2() failed (stderr)");
 
  756             action_launch_child(op);
 
  767         crm_warn(
"Could not set child output non-blocking: %s " 
  775         crm_warn(
"Could not set child error output non-blocking: %s " 
  781         action_synced_wait(op, pmask);
 
  812     struct dirent **namelist;
 
  813     int entries = 0, lpc = 0;
 
  814     char buffer[PATH_MAX];
 
  816     entries = scandir(root, &namelist, NULL, 
alphasort);
 
  821     for (lpc = 0; lpc < entries; lpc++) {
 
  824         if (
'.' == namelist[lpc]->d_name[0]) {
 
  829         snprintf(buffer, 
sizeof(buffer), 
"%s/%s", root, namelist[lpc]->d_name);
 
  831         if (stat(buffer, &sb)) {
 
  835         if (S_ISDIR(sb.st_mode)) {
 
  841         } 
else if (S_ISREG(sb.st_mode)) {
 
  842             if (files == FALSE) {
 
  846             } 
else if (executable
 
  847                        && (sb.st_mode & S_IXUSR) == 0
 
  848                        && (sb.st_mode & S_IXGRP) == 0 && (sb.st_mode & S_IXOTH) == 0) {
 
  854         list = g_list_append(list, strdup(namelist[lpc]->d_name));
 
  879     GList *result = NULL;
 
  880     GList *providers = NULL;
 
  885         snprintf(buffer, 
sizeof(buffer), 
"%s/resource.d/%s", 
OCF_ROOT_DIR, provider);
 
  890     for (gIter = providers; gIter != NULL; gIter = gIter->next) {
 
  891         GList *tmp1 = result;
 
  895             result = g_list_concat(tmp1, tmp2);
 
  898     g_list_free_full(providers, free);
 
  906     GList *plugin_list = NULL;
 
  907     GList *result = NULL;
 
  913     for (gIter = plugin_list; gIter != NULL; gIter = gIter->next) {
 
  914         const char *plugin = gIter->data;
 
  918         if (stat(metadata, &st) == 0) {
 
  919             result = g_list_append(result, strdup(plugin));
 
  924     g_list_free_full(plugin_list, free);
 
int replace_secret_params(char *rsc_id, GHashTable *params)
 
void services_action_free(svc_action_t *op)
 
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
 
#define sigchld_cleanup()
 
#define crm_log_output(level, prefix, output)
 
const char * pcmk_strerror(int rc)
 
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 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)
 
int(* dispatch)(gpointer userdata)
 
gboolean services_os_action_execute(svc_action_t *op)
 
G_GNUC_INTERNAL GList * resources_os_list_nagios_agents(void)
 
Wrappers for and extensions to glib mainloop. 
 
GList * resources_os_list_lsb_agents(void)
 
void services_action_cleanup(svc_action_t *op)
 
#define do_crm_log_unlikely(level, fmt, args...)
Log a message that is likely to be filtered out. 
 
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)
 
int crm_set_nonblocking(int fd)
 
void(* callback)(svc_action_t *op)
 
#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...)
Log a system error message. 
 
#define NAGIOS_PLUGIN_DIR
 
#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)
 
#define safe_str_eq(a, b)
 
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
 
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
 
#define crm_info(fmt, args...)
 
#define NAGIOS_METADATA_DIR
 
int mainloop_child_timeout(mainloop_child_t *child)