14 #include <sys/types.h> 23 #include <sys/resource.h> 25 #ifdef HAVE_SYS_SIGNALFD_H 26 #include <sys/signalfd.h> 35 #if SUPPORT_CIBSECRETS 40 set_fd_opts(
int fd,
int opts)
44 if ((flag = fcntl(fd, F_GETFL)) >= 0) {
45 if (fcntl(fd, F_SETFL, flag | opts) < 0) {
46 crm_err(
"fcntl() write failed");
54 svc_read_output(
int fd,
svc_action_t * op,
bool is_stderr)
59 static const size_t buf_read_len =
sizeof(buf) - 1;
70 crm_trace(
"Reading %s stderr into offset %d", op->
id, len);
75 crm_trace(
"Reading %s stdout into offset %d", op->
id, len);
78 crm_trace(
"Reading %s %s into offset %d", op->
id, is_stderr?
"stderr":
"stdout", len);
82 rc = read(fd, buf, buf_read_len);
84 crm_trace(
"Got %d chars: %.80s", rc, buf);
86 data = realloc_safe(data, len + rc + 1);
87 len += sprintf(data + len,
"%s", buf);
89 }
else if (errno != EINTR) {
97 }
while (rc == buf_read_len || rc < 0);
109 dispatch_stdout(gpointer userdata)
117 dispatch_stderr(gpointer userdata)
125 pipe_out_done(gpointer user_data)
139 pipe_err_done(gpointer user_data)
152 .destroy = pipe_out_done,
157 .destroy = pipe_err_done,
161 set_ocf_env(
const char *key,
const char *value, gpointer user_data)
163 if (
setenv(key, value, 1) != 0) {
164 crm_perror(LOG_ERR,
"setenv failed for key:%s and value:%s", key, value);
169 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
173 snprintf(buffer,
sizeof(buffer),
"OCF_RESKEY_%s", (
char *)key);
174 set_ocf_env(buffer, value, user_data);
191 g_hash_table_foreach(op->
params, set_ocf_env_with_prefix, NULL);
194 set_ocf_env(
"OCF_RA_VERSION_MAJOR",
"1", NULL);
195 set_ocf_env(
"OCF_RA_VERSION_MINOR",
"0", NULL);
200 set_ocf_env(
"OCF_RESOURCE_INSTANCE", op->
rsc, NULL);
203 if (op->
agent != NULL) {
204 set_ocf_env(
"OCF_RESOURCE_TYPE", op->
agent, NULL);
209 set_ocf_env(
"OCF_RESOURCE_PROVIDER", op->
provider, NULL);
218 crm_debug(
"Scheduling another invocation of %s", op->
id);
284 crm_trace(
"%s dispatching stderr", prefix);
295 crm_trace(
"%s dispatching stdout", prefix);
310 "%s - terminated with signal %d", prefix, signo);
317 crm_debug(
"%s - exited with rc=%d", prefix, exitcode);
342 services_handle_exec_error(
svc_action_t * op,
int error)
344 int rc_not_installed, rc_insufficient_priv, rc_exec_error;
373 op->
rc = rc_not_installed;
378 op->
rc = rc_insufficient_priv;
382 op->
rc = rc_exec_error;
397 signal(SIGPIPE, SIG_DFL);
399 #if defined(HAVE_SCHED_SETSCHEDULER) 400 if (sched_getscheduler(0) != SCHED_OTHER) {
401 struct sched_param sp;
403 memset(&sp, 0,
sizeof(sp));
404 sp.sched_priority = 0;
406 if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
407 crm_perror(LOG_ERR,
"Could not reset scheduling policy to SCHED_OTHER for %s", op->
id);
411 if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
412 crm_perror(LOG_ERR,
"Could not reset process priority to 0 for %s", op->
id);
422 for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) {
426 #if SUPPORT_CIBSECRETS 431 crm_info(
"proceeding with the stop operation for %s", op->
rsc);
434 crm_err(
"failed to get secrets for %s, " 435 "considering resource not configured", op->
rsc);
441 add_action_env_vars(op);
444 if (op->
opaque->
uid && (geteuid() == 0)) {
460 services_handle_exec_error(op, errno);
465 #ifndef HAVE_SYS_SIGNALFD_H 466 static int sigchld_pipe[2] = { -1, -1 };
471 if ((sigchld_pipe[1] >= 0) && (write(sigchld_pipe[1],
"", 1) == -1)) {
484 struct pollfd fds[3];
487 #ifdef HAVE_SYS_SIGNALFD_H 488 sfd = signalfd(-1, mask, SFD_NONBLOCK);
493 sfd = sigchld_pipe[0];
497 fds[0].events = POLLIN;
501 fds[1].events = POLLIN;
505 fds[2].events = POLLIN;
511 int poll_rc = poll(fds, 3, timeout);
514 if (fds[0].revents & POLLIN) {
518 if (fds[1].revents & POLLIN) {
522 if (fds[2].revents & POLLIN) {
523 #ifdef HAVE_SYS_SIGNALFD_H 524 struct signalfd_siginfo fdsi;
527 s = read(sfd, &fdsi,
sizeof(
struct signalfd_siginfo));
528 if (s !=
sizeof(
struct signalfd_siginfo)) {
529 crm_perror(LOG_ERR,
"Read from signal fd %d failed", sfd);
531 }
else if (fdsi.ssi_signo == SIGCHLD) {
536 while (read(sfd, &ch, 1) == 1) ;
538 wait_rc = waitpid(op->
pid, &status, WNOHANG);
543 }
else if (wait_rc < 0){
544 if (errno == ECHILD) {
557 }
else if (poll_rc == 0) {
561 }
else if (poll_rc < 0) {
562 if (errno != EINTR) {
568 timeout = op->
timeout - (time(NULL) - start) * 1000;
570 }
while ((op->
timeout < 0 || timeout > 0));
576 if (op->
timeout > 0 && timeout <= 0) {
586 if (wait_rc == 0 && waitpid(op->
pid, &status, WNOHANG) == 0) {
587 if (kill(op->
pid, SIGKILL)) {
588 crm_err(
"kill(%d, KILL) failed: %d", op->
pid, errno);
591 while (waitpid(op->
pid, &status, 0) == (pid_t) -1 && errno == EINTR) ;
594 }
else if (WIFEXITED(status)) {
596 op->
rc = WEXITSTATUS(status);
597 crm_info(
"Managed %s process %d exited with rc=%d", op->
id, op->
pid, op->
rc);
599 }
else if (WIFSIGNALED(status)) {
600 int signo = WTERMSIG(status);
603 crm_err(
"Managed %s process %d exited with signal=%d", op->
id, op->
pid, signo);
606 if (WCOREDUMP(status)) {
607 crm_err(
"Managed %s process %d dumped core", op->
id, op->
pid);
617 #ifdef HAVE_SYS_SIGNALFD_H 632 #ifdef HAVE_SYS_SIGNALFD_H 635 #define sigchld_cleanup() do { \ 636 if (sigismember(&old_mask, SIGCHLD) == 0) { \ 637 if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) { \ 638 crm_perror(LOG_ERR, "sigprocmask() failed to unblock sigchld"); \ 644 struct sigaction old_sa;
645 #define sigchld_cleanup() do { \ 646 if (sigaction(SIGCHLD, &old_sa, NULL) < 0) { \ 647 crm_perror(LOG_ERR, "sigaction() failed to remove sigchld handler"); \ 649 close(sigchld_pipe[0]); \ 650 close(sigchld_pipe[1]); \ 651 sigchld_pipe[0] = sigchld_pipe[1] = -1; \ 659 services_handle_exec_error(op, rc);
666 if (pipe(stdout_fd) < 0) {
671 services_handle_exec_error(op, rc);
678 if (pipe(stderr_fd) < 0) {
686 services_handle_exec_error(op, rc);
694 #ifdef HAVE_SYS_SIGNALFD_H 696 sigaddset(&mask, SIGCHLD);
697 sigemptyset(&old_mask);
699 if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) {
700 crm_perror(LOG_ERR,
"sigprocmask() failed to block sigchld");
705 if(pipe(sigchld_pipe) == -1) {
709 set_fd_opts(sigchld_pipe[0], O_NONBLOCK);
710 set_fd_opts(sigchld_pipe[1], O_NONBLOCK);
712 sa.sa_handler = sigchld_handler;
714 sigemptyset(&sa.sa_mask);
715 if (sigaction(SIGCHLD, &sa, &old_sa) < 0) {
716 crm_perror(LOG_ERR,
"sigaction() failed to set sigchld handler");
735 services_handle_exec_error(op, rc);
746 if (STDOUT_FILENO != stdout_fd[1]) {
747 if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
748 crm_err(
"dup2() failed (stdout)");
752 if (STDERR_FILENO != stderr_fd[1]) {
753 if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
754 crm_err(
"dup2() failed (stderr)");
763 action_launch_child(op);
778 action_synced_wait(op, pmask);
809 struct dirent **namelist;
810 int entries = 0, lpc = 0;
811 char buffer[PATH_MAX];
813 entries = scandir(root, &namelist, NULL,
alphasort);
818 for (lpc = 0; lpc < entries; lpc++) {
821 if (
'.' == namelist[lpc]->d_name[0]) {
826 snprintf(buffer,
sizeof(buffer),
"%s/%s", root, namelist[lpc]->d_name);
828 if (stat(buffer, &sb)) {
832 if (S_ISDIR(sb.st_mode)) {
838 }
else if (S_ISREG(sb.st_mode)) {
839 if (files == FALSE) {
843 }
else if (executable
844 && (sb.st_mode & S_IXUSR) == 0
845 && (sb.st_mode & S_IXGRP) == 0 && (sb.st_mode & S_IXOTH) == 0) {
851 list = g_list_append(list, strdup(namelist[lpc]->d_name));
876 GList *result = NULL;
877 GList *providers = NULL;
882 snprintf(buffer,
sizeof(buffer),
"%s/resource.d/%s",
OCF_ROOT_DIR, provider);
887 for (gIter = providers; gIter != NULL; gIter = gIter->next) {
888 GList *tmp1 = result;
892 result = g_list_concat(tmp1, tmp2);
895 g_list_free_full(providers, free);
903 GList *plugin_list = NULL;
904 GList *result = NULL;
910 for (gIter = plugin_list; gIter != NULL; gIter = gIter->next) {
911 const char *plugin = gIter->data;
915 if (stat(metadata, &st) == 0) {
916 result = g_list_append(result, strdup(plugin));
921 g_list_free_full(plugin_list, free);
int replace_secret_params(char *rsc_id, GHashTable *params)
void(* callback)(svc_action_t *op)
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)
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)
int(* dispatch)(gpointer userdata)
#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)
#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)