14 #include <sys/types.h> 22 #include <sys/resource.h> 30 #if SUPPORT_CIBSECRETS 42 #ifdef HAVE_SYS_SIGNALFD_H 46 #include <sys/signalfd.h> 49 struct sigchld_data_s {
56 sigchld_setup(
struct sigchld_data_s *
data)
58 sigemptyset(&(data->mask));
59 sigaddset(&(data->mask), SIGCHLD);
61 sigemptyset(&(data->old_mask));
64 if (sigprocmask(SIG_BLOCK, &(data->mask), &(data->old_mask)) < 0) {
65 crm_perror(LOG_ERR,
"sigprocmask() failed to block sigchld");
71 sigchld_open(
struct sigchld_data_s *data)
77 fd = signalfd(-1, &(data->mask), SFD_NONBLOCK);
95 sigchld_received(
int fd)
97 struct signalfd_siginfo fdsi;
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);
104 }
else if (fdsi.ssi_signo == SIGCHLD) {
112 sigchld_cleanup(
struct sigchld_data_s *data)
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");
121 #else // HAVE_SYS_SIGNALFD_H not defined 125 struct sigchld_data_s {
128 struct sigaction old_sa;
138 if ((last_sigchld_data != NULL)
139 && (last_sigchld_data->pipe_fd[1] >= 0)
140 && (write(last_sigchld_data->pipe_fd[1],
"", 1) == -1)) {
146 sigchld_setup(
struct sigchld_data_s *data)
150 data->pipe_fd[0] = data->pipe_fd[1] = -1;
152 if (pipe(data->pipe_fd) == -1) {
158 crm_warn(
"Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
163 crm_warn(
"Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
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");
176 last_sigchld_data =
data;
180 sigchld_open(
struct sigchld_data_s *data)
183 return data->pipe_fd[0];
187 sigchld_close(
int fd)
194 sigchld_received(
int fd)
199 while (read(fd, &ch, 1) == 1) ;
204 sigchld_cleanup(
struct sigchld_data_s *data)
207 if (sigaction(SIGCHLD, &(data->old_sa), NULL) < 0) {
208 crm_perror(LOG_ERR,
"sigaction() failed to remove sigchld handler");
212 if (data->pipe_fd[0] >= 0) {
213 close(data->pipe_fd[0]);
214 data->pipe_fd[0] = -1;
216 if (data->pipe_fd[1] >= 0) {
217 close(data->pipe_fd[1]);
218 data->pipe_fd[1] = -1;
225 svc_read_output(
int fd,
svc_action_t * op,
bool is_stderr)
230 static const size_t buf_read_len =
sizeof(buf) - 1;
241 crm_trace(
"Reading %s stderr into offset %d", op->
id, len);
243 }
else if (is_stderr == FALSE && op->
stdout_data) {
246 crm_trace(
"Reading %s stdout into offset %d", op->
id, len);
249 crm_trace(
"Reading %s %s into offset %d", op->
id, is_stderr?
"stderr":
"stdout", len);
253 rc = read(fd, buf, buf_read_len);
256 crm_trace(
"Got %d chars: %.80s", rc, buf);
257 data = realloc_safe(data, len + rc + 1);
258 len += sprintf(data + len,
"%s", buf);
260 }
else if (errno != EINTR) {
268 }
while (rc == buf_read_len || rc < 0);
280 dispatch_stdout(gpointer userdata)
288 dispatch_stderr(gpointer userdata)
296 pipe_out_done(gpointer user_data)
310 pipe_err_done(gpointer user_data)
323 .destroy = pipe_out_done,
328 .destroy = pipe_err_done,
332 set_ocf_env(
const char *key,
const char *value, gpointer user_data)
334 if (
setenv(key, value, 1) != 0) {
335 crm_perror(LOG_ERR,
"setenv failed for key:%s and value:%s", key, value);
340 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
344 snprintf(buffer,
sizeof(buffer),
"OCF_RESKEY_%s", (
char *)key);
345 set_ocf_env(buffer, value, user_data);
349 set_alert_env(gpointer key, gpointer value, gpointer user_data)
354 rc =
setenv(key, value, 1);
361 (
char*)key, (value? (
char*)value :
""));
363 crm_trace(
"setenv %s=%s", (
char*)key, (value? (
char*)value :
""));
376 void (*env_setter)(gpointer, gpointer, gpointer) = NULL;
377 if (op->
agent == NULL) {
378 env_setter = set_alert_env;
381 env_setter = set_ocf_env_with_prefix;
384 if (env_setter != NULL && op->
params != NULL) {
385 g_hash_table_foreach(op->
params, env_setter, NULL);
388 if (env_setter == NULL || env_setter == set_alert_env) {
392 set_ocf_env(
"OCF_RA_VERSION_MAJOR",
"1", NULL);
393 set_ocf_env(
"OCF_RA_VERSION_MINOR",
"0", NULL);
398 set_ocf_env(
"OCF_RESOURCE_INSTANCE", op->
rsc, NULL);
401 if (op->
agent != NULL) {
402 set_ocf_env(
"OCF_RESOURCE_TYPE", op->
agent, NULL);
407 set_ocf_env(
"OCF_RESOURCE_PROVIDER", op->
provider, NULL);
412 pipe_in_single_parameter(gpointer key, gpointer value, gpointer user_data)
416 int ret, total = 0, len = strlen(buffer);
425 }
while ((errno == EINTR) && (total < len));
440 g_hash_table_foreach(op->
params, pipe_in_single_parameter, (gpointer) op);
449 crm_debug(
"Scheduling another invocation of %s", op->
id);
515 crm_trace(
"%s dispatching stderr", prefix);
526 crm_trace(
"%s dispatching stdout", prefix);
547 crm_info(
"%s - terminated with signal %d", prefix, signo);
552 crm_warn(
"%s - terminated with signal %d", prefix, signo);
559 crm_debug(
"%s - exited with rc=%d", prefix, exitcode);
584 services_handle_exec_error(
svc_action_t * op,
int error)
586 int rc_not_installed, rc_insufficient_priv, rc_exec_error;
615 op->
rc = rc_not_installed;
620 op->
rc = rc_insufficient_priv;
624 op->
rc = rc_exec_error;
637 signal(SIGPIPE, SIG_DFL);
639 #if defined(HAVE_SCHED_SETSCHEDULER) 640 if (sched_getscheduler(0) != SCHED_OTHER) {
641 struct sched_param sp;
643 memset(&sp, 0,
sizeof(sp));
644 sp.sched_priority = 0;
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);
651 if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
652 crm_perror(LOG_ERR,
"Could not reset process priority to 0 for %s", op->
id);
663 #if SUPPORT_CIBSECRETS 668 crm_info(
"proceeding with the stop operation for %s", op->
rsc);
671 crm_err(
"failed to get secrets for %s, " 672 "considering resource not configured", op->
rsc);
678 add_action_env_vars(op);
681 if (op->
opaque->
uid && (geteuid() == 0)) {
697 services_handle_exec_error(op, errno);
703 action_synced_wait(
svc_action_t *op,
struct sigchld_data_s *data)
708 struct pollfd fds[3];
712 fds[0].events = POLLIN;
716 fds[1].events = POLLIN;
719 fds[2].fd = sigchld_open(data);
720 fds[2].events = POLLIN;
726 int poll_rc = poll(fds, 3, timeout);
729 if (fds[0].revents & POLLIN) {
733 if (fds[1].revents & POLLIN) {
737 if ((fds[2].revents & POLLIN) && sigchld_received(fds[2].fd)) {
738 wait_rc = waitpid(op->
pid, &status, WNOHANG);
743 }
else if (wait_rc < 0) {
744 if (errno == ECHILD) {
756 }
else if (poll_rc == 0) {
760 }
else if (poll_rc < 0) {
761 if (errno != EINTR) {
767 timeout = op->
timeout - (time(NULL) - start) * 1000;
769 }
while ((op->
timeout < 0 || timeout > 0));
775 if (op->
timeout > 0 && timeout <= 0) {
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);
790 while (waitpid(op->
pid, &status, 0) == (pid_t) -1 && errno == EINTR) ;
793 }
else if (WIFEXITED(status)) {
795 op->
rc = WEXITSTATUS(status);
796 crm_info(
"Managed %s process %d exited with rc=%d", op->
id, op->
pid, op->
rc);
798 }
else if (WIFSIGNALED(status)) {
799 int signo = WTERMSIG(status);
802 crm_err(
"Managed %s process %d exited with signal=%d", op->
id, op->
pid, signo);
805 if (WCOREDUMP(status)) {
806 crm_err(
"Managed %s process %d dumped core", op->
id, op->
pid);
818 sigchld_close(fds[2].fd);
828 int stdin_fd[2] = {-1, -1};
831 struct sigchld_data_s data;
837 services_handle_exec_error(op, rc);
844 if (pipe(stdout_fd) < 0) {
849 services_handle_exec_error(op, rc);
856 if (pipe(stderr_fd) < 0) {
864 services_handle_exec_error(op, rc);
872 if (pipe(stdin_fd) < 0) {
882 services_handle_exec_error(op, rc);
891 sigchld_setup(&data);
903 if (stdin_fd[0] >= 0) {
909 services_handle_exec_error(op, rc);
914 sigchld_cleanup(&data);
920 if (stdin_fd[1] >= 0) {
923 if (STDOUT_FILENO != stdout_fd[1]) {
924 if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
925 crm_err(
"dup2() failed (stdout)");
929 if (STDERR_FILENO != stderr_fd[1]) {
930 if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
931 crm_err(
"dup2() failed (stderr)");
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)");
944 sigchld_cleanup(&data);
947 action_launch_child(op);
954 if (stdin_fd[0] >= 0) {
961 crm_warn(
"Could not set child output non-blocking: %s " 969 crm_warn(
"Could not set child error output non-blocking: %s " 980 crm_warn(
"Could not set child input non-blocking: %s " 984 pipe_in_action_stdin_parameters(op);
996 action_synced_wait(op, &data);
997 sigchld_cleanup(&data);
1006 operation_finished);
1027 struct dirent **namelist;
1028 int entries = 0, lpc = 0;
1029 char buffer[PATH_MAX];
1031 entries = scandir(root, &namelist, NULL,
alphasort);
1036 for (lpc = 0; lpc < entries; lpc++) {
1039 if (
'.' == namelist[lpc]->d_name[0]) {
1040 free(namelist[lpc]);
1044 snprintf(buffer,
sizeof(buffer),
"%s/%s", root, namelist[lpc]->d_name);
1046 if (stat(buffer, &sb)) {
1050 if (S_ISDIR(sb.st_mode)) {
1052 free(namelist[lpc]);
1056 }
else if (S_ISREG(sb.st_mode)) {
1057 if (files == FALSE) {
1058 free(namelist[lpc]);
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]);
1069 list = g_list_append(list, strdup(namelist[lpc]->d_name));
1071 free(namelist[lpc]);
1093 GList *gIter = NULL;
1094 GList *result = NULL;
1095 GList *providers = NULL;
1100 snprintf(buffer,
sizeof(buffer),
"%s/resource.d/%s",
OCF_ROOT_DIR, provider);
1105 for (gIter = providers; gIter != NULL; gIter = gIter->next) {
1106 GList *tmp1 = result;
1110 result = g_list_concat(tmp1, tmp2);
1113 g_list_free_full(providers, free);
1121 GList *plugin_list = NULL;
1122 GList *result = NULL;
1123 GList *gIter = NULL;
1128 for (gIter = plugin_list; gIter != NULL; gIter = gIter->next) {
1129 const char *plugin = gIter->data;
1133 if (stat(metadata, &st) == 0) {
1134 result = g_list_append(result, strdup(plugin));
1139 g_list_free_full(plugin_list, free);
#define CRM_CHECK(expr, failure_action)
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 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 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)
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)
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)
int crm_set_nonblocking(int fd)
#define PCMK_OCF_REASON_PREFIX
#define PCMK_RESOURCE_CLASS_STONITH
void services_add_inflight_op(svc_action_t *op)
void services_untrack_op(svc_action_t *op)
int replace_secret_params(const char *rsc_id, GHashTable *params)
#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 *))
void(* fork_callback)(svc_action_t *op)
#define crm_info(fmt, args...)
#define NAGIOS_METADATA_DIR
int mainloop_child_timeout(mainloop_child_t *child)