27 #include "dbus-spawn.h"
28 #include "dbus-sysdeps-unix.h"
29 #include "dbus-internals.h"
30 #include "dbus-test.h"
31 #include "dbus-protocol.h"
45 #include <systemd/sd-journal.h>
48 #if defined(__APPLE__)
49 # include <crt_externs.h>
50 # define environ (*_NSGetEnviron ())
51 #elif !HAVE_DECL_ENVIRON
52 extern char **environ;
85 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
94 to_read =
sizeof (int) * n_ints_in_buf - bytes;
102 ((
char*)buf) + bytes,
105 if (chunk < 0 && errno == EINTR)
112 "Failed to read from child pipe (%s)",
113 _dbus_strerror (errno));
127 *n_ints_read = (int)(bytes /
sizeof(
int));
140 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
149 to_read =
sizeof (pid_t) - bytes;
157 ((
char*)buf) + bytes,
159 if (chunk < 0 && errno == EINTR)
166 "Failed to read from child pipe (%s)",
167 _dbus_strerror (errno));
262 DBusBabysitterFinishedFunc finished_cb;
267 unsigned int have_child_status : 1;
273 _dbus_babysitter_new (
void)
281 sitter->refcount = 1;
312 sitter->refcount += 1;
334 sitter->refcount -= 1;
335 if (sitter->refcount == 0)
344 close_socket_to_babysitter (sitter);
346 close_error_pipe_from_child (sitter);
357 ret = waitpid (sitter->
sitter_pid, &status, WNOHANG);
369 ret = waitpid (sitter->
sitter_pid, &status, 0);
371 while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
377 _dbus_warn (
"Babysitter process not available to be reaped; should not happen");
379 _dbus_warn (
"Unexpected error %d in waitpid() for babysitter: %s",
380 errno, _dbus_strerror (errno));
384 _dbus_verbose (
"Reaped %ld, waiting for babysitter %ld\n",
387 if (WIFEXITED (sitter->
status))
388 _dbus_verbose (
"Babysitter exited with status %d\n",
389 WEXITSTATUS (sitter->
status));
390 else if (WIFSIGNALED (sitter->
status))
391 _dbus_verbose (
"Babysitter received signal %d\n",
392 WTERMSIG (sitter->
status));
394 _dbus_verbose (
"Babysitter exited abnormally\n");
418 r = read_ints (fd, &what, 1, &got, &error);
443 case CHILD_FORK_FAILED:
444 case CHILD_EXEC_FAILED:
448 r = read_ints (fd, &arg, 1, &got, &error);
467 if (what == CHILD_EXITED)
486 sitter->have_child_status =
TRUE;
488 _dbus_verbose (
"recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
489 WIFEXITED (sitter->
status), WIFSIGNALED (sitter->
status),
490 WEXITSTATUS (sitter->
status), WTERMSIG (sitter->
status));
492 else if (what == CHILD_FORK_FAILED)
496 _dbus_verbose (
"recorded fork errnum %d\n", sitter->
errnum);
498 else if (what == CHILD_EXEC_FAILED)
502 _dbus_verbose (
"recorded exec errnum %d\n", sitter->
errnum);
511 r = read_pid (fd, &pid, &error);
530 _dbus_verbose (
"recorded grandchild pid %d\n", sitter->
grandchild_pid);
534 _dbus_warn (
"Unknown message received from babysitter process");
545 _dbus_verbose (
"Closing babysitter\n");
566 _dbus_verbose (
"Closing child error\n");
594 _dbus_verbose (
"Reading data from babysitter\n");
596 close_socket_to_babysitter (sitter);
600 close_socket_to_babysitter (sitter);
608 if (revents & _DBUS_POLLIN)
610 _dbus_verbose (
"Reading data from child error\n");
612 close_error_pipe_from_child (sitter);
616 close_error_pipe_from_child (sitter);
629 descriptors_ready =
FALSE;
657 while (ret < 0 && errno == EINTR);
659 if (ret == 0 && block)
665 while (ret < 0 && errno == EINTR);
670 descriptors_ready =
TRUE;
676 handle_error_pipe (sitter, fds[i].revents);
678 handle_babysitter_socket (sitter, fds[i].revents);
683 return descriptors_ready;
690 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter.fd >= 0 || (sitter)->error_pipe_from_child >= 0)
704 babysitter_iteration (sitter,
TRUE);
706 _dbus_verbose (
"Got child PID %ld for killing\n",
726 babysitter_iteration (sitter,
FALSE))
752 if (!sitter->have_child_status ||
753 !(WIFEXITED (sitter->
status)))
756 *status = WEXITSTATUS (sitter->
status);
783 "Failed to execute program %s: %s",
789 "Failed to fork a new process %s: %s",
792 else if (sitter->have_child_status)
794 if (WIFEXITED (sitter->
status))
796 "Process %s exited with status %d",
798 else if (WIFSIGNALED (sitter->
status))
800 "Process %s received signal %d",
804 "Process %s exited abnormally",
810 "Process %s exited, reason unknown",
845 unsigned int condition,
863 handle_error_pipe (sitter, revents);
865 handle_babysitter_socket (sitter, revents);
868 babysitter_iteration (sitter,
FALSE))
877 sitter->finished_cb !=
NULL)
879 sitter->finished_cb (sitter, sitter->finished_data);
880 sitter->finished_cb =
NULL;
903 close_and_invalidate (
int *fd)
927 retval = pipe2 (p, O_CLOEXEC);
928 cloexec_done = retval >= 0;
932 if (retval < 0 && errno == ENOSYS)
938 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
944 "Failed to create pipe for communicating with child process (%s)",
945 _dbus_strerror (errno));
961 do_write (
int fd,
const void *buf,
size_t count)
963 size_t bytes_written;
970 ret = write (fd, ((
const char*)buf) + bytes_written, count - bytes_written);
983 bytes_written += ret;
985 if (bytes_written < count)
989 static void write_err_and_exit (
int fd,
int msg) _DBUS_GNUC_NORETURN;
992 write_err_and_exit (
int fd,
int msg)
996 do_write (fd, &msg,
sizeof (msg));
997 do_write (fd, &en,
sizeof (en));
1003 write_pid (
int fd, pid_t pid)
1005 int msg = CHILD_PID;
1007 do_write (fd, &msg,
sizeof (msg));
1008 do_write (fd, &pid,
sizeof (pid));
1011 static void write_status_and_exit (
int fd,
int status) _DBUS_GNUC_NORETURN;
1014 write_status_and_exit (
int fd,
int status)
1016 int msg = CHILD_EXITED;
1018 do_write (fd, &msg,
sizeof (msg));
1019 do_write (fd, &status,
sizeof (status));
1024 static void do_exec (
int child_err_report_fd,
1027 DBusSpawnChildSetupFunc child_setup,
1028 void *user_data) _DBUS_GNUC_NORETURN;
1031 do_exec (
int child_err_report_fd,
1034 DBusSpawnChildSetupFunc child_setup,
1037 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1041 _dbus_verbose_reset ();
1046 (* child_setup) (user_data);
1048 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1049 max_open = sysconf (_SC_OPEN_MAX);
1051 for (i = 3; i < max_open; i++)
1055 if (i == child_err_report_fd)
1058 retval = fcntl (i, F_GETFD);
1060 if (retval != -1 && !(retval & FD_CLOEXEC))
1061 _dbus_warn (
"Fd %d did not have the close-on-exec flag set!", i);
1072 execve (argv[0], argv, envp);
1075 write_err_and_exit (child_err_report_fd,
1080 check_babysit_events (pid_t grandchild_pid,
1089 ret = waitpid (grandchild_pid, &status, WNOHANG);
1094 while (ret < 0 && errno == EINTR);
1098 _dbus_verbose (
"no child exited\n");
1105 _dbus_warn (
"unexpected waitpid() failure in check_babysit_events(): %s",
1106 _dbus_strerror (errno));
1109 else if (ret == grandchild_pid)
1112 _dbus_verbose (
"reaped child pid %ld\n", (
long) ret);
1114 write_status_and_exit (parent_pipe, status);
1118 _dbus_warn (
"waitpid() reaped pid %d that we've never heard of",
1123 if (revents & _DBUS_POLLIN)
1125 _dbus_verbose (
"babysitter got POLLIN from parent pipe\n");
1131 _dbus_verbose (
"babysitter got POLLERR or POLLHUP from parent\n");
1136 static int babysit_sigchld_pipe = -1;
1139 babysit_signal_handler (
int signo)
1143 int saved_errno = errno;
1147 if (write (babysit_sigchld_pipe, &b, 1) <= 0)
1151 errno = saved_errno;
1154 static void babysit (pid_t grandchild_pid,
1155 int parent_pipe) _DBUS_GNUC_NORETURN;
1158 babysit (pid_t grandchild_pid,
1161 int sigchld_pipe[2];
1166 _dbus_verbose_reset ();
1173 if (pipe (sigchld_pipe) < 0)
1175 _dbus_warn (
"Not enough file descriptors to create pipe in babysitter process");
1179 babysit_sigchld_pipe = sigchld_pipe[
WRITE_END];
1183 write_pid (parent_pipe, grandchild_pid);
1185 check_babysit_events (grandchild_pid, parent_pipe, 0);
1191 pfds[0].
fd = parent_pipe;
1201 _dbus_warn (
"_dbus_poll() error: %s", strerror (errno));
1205 if (pfds[0].revents != 0)
1207 check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
1209 else if (pfds[1].revents & _DBUS_POLLIN)
1212 if (read (sigchld_pipe[
READ_END], &b, 1) == -1)
1217 check_babysit_events (grandchild_pid, parent_pipe, 0);
1250 const char *log_name,
1253 DBusSpawnFlags flags,
1254 DBusSpawnChildSetupFunc child_setup,
1259 int child_err_report_pipe[2] = { -1, -1 };
1260 DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT };
1267 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1270 if (sitter_p !=
NULL)
1275 sitter = _dbus_babysitter_new ();
1286 goto cleanup_and_fail;
1295 goto cleanup_and_fail;
1298 if (!make_pipe (child_err_report_pipe, error))
1299 goto cleanup_and_fail;
1302 goto cleanup_and_fail;
1310 DBUS_WATCH_READABLE,
1315 goto cleanup_and_fail;
1327 goto cleanup_and_fail;
1331 DBUS_WATCH_READABLE,
1336 goto cleanup_and_fail;
1348 goto cleanup_and_fail;
1351 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1354 if (flags & DBUS_SPAWN_REDIRECT_OUTPUT)
1360 fd_out = sd_journal_stream_fd (sitter->
log_name, LOG_INFO,
FALSE);
1361 fd_err = sd_journal_stream_fd (sitter->
log_name, LOG_WARNING,
FALSE);
1371 "Failed to fork (%s)",
1372 _dbus_strerror (errno));
1373 goto cleanup_and_fail;
1383 signal (SIGPIPE, SIG_DFL);
1386 close_and_invalidate (&child_err_report_pipe[READ_END]);
1387 close_and_invalidate (&babysitter_pipe[0].fd);
1390 grandchild_pid = fork ();
1392 if (grandchild_pid < 0)
1394 write_err_and_exit (babysitter_pipe[1].fd,
1398 else if (grandchild_pid == 0)
1404 fd = open (
"/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
1409 fd = open (
"/proc/self/oom_score_adj", O_WRONLY);
1415 if (write (fd,
"0",
sizeof (
char)) < 0)
1416 _dbus_warn (
"writing oom_score_adj error: %s", strerror (errno));
1422 signal (SIGPIPE, SIG_IGN);
1424 close_and_invalidate (&babysitter_pipe[1].fd);
1428 dup2 (fd_out, STDOUT_FILENO);
1430 dup2 (fd_err, STDERR_FILENO);
1431 close_and_invalidate (&fd_out);
1432 close_and_invalidate (&fd_err);
1434 do_exec (child_err_report_pipe[
WRITE_END],
1437 child_setup, user_data);
1442 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1444 close_and_invalidate (&fd_out);
1445 close_and_invalidate (&fd_err);
1447 babysit (grandchild_pid, babysitter_pipe[1].fd);
1454 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1455 close_and_invalidate (&babysitter_pipe[1].fd);
1457 close_and_invalidate (&fd_out);
1458 close_and_invalidate (&fd_err);
1462 babysitter_pipe[0].fd = -1;
1465 child_err_report_pipe[
READ_END] = -1;
1469 if (sitter_p !=
NULL)
1476 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1483 _DBUS_ASSERT_ERROR_IS_SET (error);
1485 close_and_invalidate (&child_err_report_pipe[READ_END]);
1486 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1487 close_and_invalidate (&babysitter_pipe[0].fd);
1488 close_and_invalidate (&babysitter_pipe[1].fd);
1490 close_and_invalidate (&fd_out);
1491 close_and_invalidate (&fd_err);
1502 DBusBabysitterFinishedFunc finished,
1505 sitter->finished_cb = finished;
1506 sitter->finished_data = user_data;
1515 babysitter_iteration (sitter,
TRUE);