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"
42 extern char **environ;
74 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
83 to_read =
sizeof (int) * n_ints_in_buf - bytes;
94 if (chunk < 0 && errno == EINTR)
101 "Failed to read from child pipe (%s)",
102 _dbus_strerror (errno));
116 *n_ints_read = (int)(bytes /
sizeof(
int));
129 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
138 to_read =
sizeof (pid_t) - bytes;
146 ((
char*)buf) + bytes,
148 if (chunk < 0 && errno == EINTR)
155 "Failed to read from child pipe (%s)",
156 _dbus_strerror (errno));
210 unsigned int have_child_status : 1;
216 _dbus_babysitter_new (
void)
305 ret = waitpid (sitter->
sitter_pid, &status, WNOHANG);
315 ret = waitpid (sitter->
sitter_pid, &status, 0);
321 else if (errno == ECHILD)
322 _dbus_warn (
"Babysitter process not available to be reaped; should not happen\n");
324 _dbus_warn (
"Unexpected error %d in waitpid() for babysitter: %s\n",
325 errno, _dbus_strerror (errno));
329 _dbus_verbose (
"Reaped %ld, waiting for babysitter %ld\n",
332 if (WIFEXITED (sitter->
status))
333 _dbus_verbose (
"Babysitter exited with status %d\n",
334 WEXITSTATUS (sitter->
status));
335 else if (WIFSIGNALED (sitter->
status))
336 _dbus_verbose (
"Babysitter received signal %d\n",
337 WTERMSIG (sitter->
status));
339 _dbus_verbose (
"Babysitter exited abnormally\n");
377 r = read_ints (fd, &what, 1, &got, &error);
398 case CHILD_FORK_FAILED:
399 case CHILD_EXEC_FAILED:
403 r = read_ints (fd, &arg, 1, &got, &error);
419 if (what == CHILD_EXITED)
421 sitter->have_child_status =
TRUE;
424 _dbus_verbose (
"recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
425 WIFEXITED (sitter->
status), WIFSIGNALED (sitter->
status),
426 WEXITSTATUS (sitter->
status), WTERMSIG (sitter->
status));
428 else if (what == CHILD_FORK_FAILED)
432 _dbus_verbose (
"recorded fork errnum %d\n", sitter->
errnum);
434 else if (what == CHILD_EXEC_FAILED)
438 _dbus_verbose (
"recorded exec errnum %d\n", sitter->
errnum);
447 r = read_pid (fd, &pid, &error);
463 _dbus_verbose (
"recorded grandchild pid %d\n", sitter->
grandchild_pid);
467 _dbus_warn (
"Unknown message received from babysitter process\n");
478 _dbus_verbose (
"Closing babysitter\n");
486 _dbus_verbose (
"Closing child error\n");
501 _dbus_verbose (
"Reading data from babysitter\n");
503 close_socket_to_babysitter (sitter);
507 close_socket_to_babysitter (sitter);
515 if (revents & _DBUS_POLLIN)
517 _dbus_verbose (
"Reading data from child error\n");
519 close_error_pipe_from_child (sitter);
523 close_error_pipe_from_child (sitter);
536 descriptors_ready =
FALSE;
564 while (ret < 0 && errno == EINTR);
566 if (ret == 0 && block)
572 while (ret < 0 && errno == EINTR);
577 descriptors_ready =
TRUE;
583 handle_error_pipe (sitter, fds[i].revents);
585 handle_babysitter_socket (sitter, fds[i].revents);
590 return descriptors_ready;
597 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
611 babysitter_iteration (sitter,
TRUE);
613 _dbus_verbose (
"Got child PID %ld for killing\n",
633 babysitter_iteration (sitter,
FALSE))
659 if (!sitter->have_child_status ||
660 !(WIFEXITED (sitter->
status)))
663 *status = WEXITSTATUS (sitter->
status);
690 "Failed to execute program %s: %s",
696 "Failed to fork a new process %s: %s",
699 else if (sitter->have_child_status)
701 if (WIFEXITED (sitter->
status))
703 "Process %s exited with status %d",
705 else if (WIFSIGNALED (sitter->
status))
707 "Process %s received signal %d",
711 "Process %s exited abnormally",
717 "Process %s exited, reason unknown",
752 unsigned int condition,
770 handle_error_pipe (sitter, revents);
772 handle_babysitter_socket (sitter, revents);
775 babysitter_iteration (sitter,
FALSE))
817 close_and_invalidate (
int *fd)
841 retval = pipe2 (p, O_CLOEXEC);
842 cloexec_done = retval >= 0;
846 if (retval < 0 && errno == ENOSYS)
852 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
858 "Failed to create pipe for communicating with child process (%s)",
859 _dbus_strerror (errno));
875 do_write (
int fd,
const void *buf,
size_t count)
877 size_t bytes_written;
884 ret = write (fd, ((
const char*)buf) + bytes_written, count - bytes_written);
892 _dbus_warn (
"Failed to write data to pipe!\n");
897 bytes_written += ret;
899 if (bytes_written < count)
904 write_err_and_exit (
int fd,
int msg)
908 do_write (fd, &msg,
sizeof (msg));
909 do_write (fd, &en,
sizeof (en));
915 write_pid (
int fd, pid_t pid)
919 do_write (fd, &msg,
sizeof (msg));
920 do_write (fd, &pid,
sizeof (pid));
924 write_status_and_exit (
int fd,
int status)
926 int msg = CHILD_EXITED;
928 do_write (fd, &msg,
sizeof (msg));
929 do_write (fd, &status,
sizeof (status));
935 do_exec (
int child_err_report_fd,
938 DBusSpawnChildSetupFunc child_setup,
941 #ifdef DBUS_BUILD_TESTS
945 _dbus_verbose_reset ();
950 (* child_setup) (user_data);
952 #ifdef DBUS_BUILD_TESTS
953 max_open = sysconf (_SC_OPEN_MAX);
955 for (i = 3; i < max_open; i++)
959 if (i == child_err_report_fd)
962 retval = fcntl (i, F_GETFD);
964 if (retval != -1 && !(retval & FD_CLOEXEC))
965 _dbus_warn (
"Fd %d did not have the close-on-exec flag set!\n", i);
976 execve (argv[0], argv, envp);
979 write_err_and_exit (child_err_report_fd,
984 check_babysit_events (pid_t grandchild_pid,
993 ret = waitpid (grandchild_pid, &status, WNOHANG);
998 while (ret < 0 && errno == EINTR);
1002 _dbus_verbose (
"no child exited\n");
1009 _dbus_warn (
"unexpected waitpid() failure in check_babysit_events(): %s\n",
1010 _dbus_strerror (errno));
1013 else if (ret == grandchild_pid)
1016 _dbus_verbose (
"reaped child pid %ld\n", (
long) ret);
1018 write_status_and_exit (parent_pipe, status);
1022 _dbus_warn (
"waitpid() reaped pid %d that we've never heard of\n",
1027 if (revents & _DBUS_POLLIN)
1029 _dbus_verbose (
"babysitter got POLLIN from parent pipe\n");
1035 _dbus_verbose (
"babysitter got POLLERR or POLLHUP from parent\n");
1040 static int babysit_sigchld_pipe = -1;
1043 babysit_signal_handler (
int signo)
1047 if (write (babysit_sigchld_pipe, &b, 1) <= 0)
1053 babysit (pid_t grandchild_pid,
1056 int sigchld_pipe[2];
1061 _dbus_verbose_reset ();
1068 if (pipe (sigchld_pipe) < 0)
1070 _dbus_warn (
"Not enough file descriptors to create pipe in babysitter process\n");
1074 babysit_sigchld_pipe = sigchld_pipe[
WRITE_END];
1078 write_pid (parent_pipe, grandchild_pid);
1080 check_babysit_events (grandchild_pid, parent_pipe, 0);
1086 pfds[0].
fd = parent_pipe;
1096 _dbus_warn (
"_dbus_poll() error: %s\n", strerror (errno));
1100 if (pfds[0].revents != 0)
1102 check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
1104 else if (pfds[1].revents & _DBUS_POLLIN)
1107 if (read (sigchld_pipe[
READ_END], &b, 1) == -1)
1110 check_babysit_events (grandchild_pid, parent_pipe, 0);
1140 DBusSpawnChildSetupFunc child_setup,
1145 int child_err_report_pipe[2] = { -1, -1 };
1146 int babysitter_pipe[2] = { -1, -1 };
1149 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1151 if (sitter_p !=
NULL)
1156 sitter = _dbus_babysitter_new ();
1167 goto cleanup_and_fail;
1170 if (!make_pipe (child_err_report_pipe, error))
1171 goto cleanup_and_fail;
1174 goto cleanup_and_fail;
1182 DBUS_WATCH_READABLE,
1187 goto cleanup_and_fail;
1193 goto cleanup_and_fail;
1197 DBUS_WATCH_READABLE,
1202 goto cleanup_and_fail;
1208 goto cleanup_and_fail;
1211 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1219 "Failed to fork (%s)",
1220 _dbus_strerror (errno));
1221 goto cleanup_and_fail;
1231 signal (SIGPIPE, SIG_DFL);
1234 close_and_invalidate (&child_err_report_pipe[READ_END]);
1235 close_and_invalidate (&babysitter_pipe[0]);
1238 grandchild_pid = fork ();
1240 if (grandchild_pid < 0)
1242 write_err_and_exit (babysitter_pipe[1],
1246 else if (grandchild_pid == 0)
1248 do_exec (child_err_report_pipe[
WRITE_END],
1251 child_setup, user_data);
1256 babysit (grandchild_pid, babysitter_pipe[1]);
1263 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1264 close_and_invalidate (&babysitter_pipe[1]);
1267 babysitter_pipe[0] = -1;
1270 child_err_report_pipe[
READ_END] = -1;
1274 if (sitter_p !=
NULL)
1281 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1288 _DBUS_ASSERT_ERROR_IS_SET (error);
1290 close_and_invalidate (&child_err_report_pipe[READ_END]);
1291 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1292 close_and_invalidate (&babysitter_pipe[0]);
1293 close_and_invalidate (&babysitter_pipe[1]);
1303 #ifdef DBUS_BUILD_TESTS
1309 babysitter_iteration (sitter,
TRUE);
1313 check_spawn_nonexistent (
void *data)
1321 argv[0] =
"/this/does/not/exist/32542sdgafgafdg";
1326 _dbus_babysitter_block_for_child_exit (sitter);
1335 _dbus_warn (
"Did not get an error launching nonexistent executable\n");
1342 _dbus_warn (
"Not expecting error when launching nonexistent executable: %s: %s\n",
1354 check_spawn_segfault (
void *data)
1362 argv[0] = TEST_SEGFAULT_BINARY;
1367 _dbus_babysitter_block_for_child_exit (sitter);
1376 _dbus_warn (
"Did not get an error launching segfaulting binary\n");
1383 _dbus_warn (
"Not expecting error when launching segfaulting executable: %s: %s\n",
1395 check_spawn_exit (
void *data)
1403 argv[0] = TEST_EXIT_BINARY;
1408 _dbus_babysitter_block_for_child_exit (sitter);
1417 _dbus_warn (
"Did not get an error launching binary that exited with failure code\n");
1424 _dbus_warn (
"Not expecting error when launching exiting executable: %s: %s\n",
1436 check_spawn_and_kill (
void *data)
1444 argv[0] = TEST_SLEEP_FOREVER_BINARY;
1451 _dbus_babysitter_block_for_child_exit (sitter);
1461 _dbus_warn (
"Did not get an error after killing spawned binary\n");
1468 _dbus_warn (
"Not expecting error when killing executable: %s: %s\n",
1480 _dbus_spawn_test (
const char *test_data_dir)
1482 if (!_dbus_test_oom_handling (
"spawn_nonexistent",
1483 check_spawn_nonexistent,
1487 if (!_dbus_test_oom_handling (
"spawn_segfault",
1488 check_spawn_segfault,
1492 if (!_dbus_test_oom_handling (
"spawn_exit",
1497 if (!_dbus_test_oom_handling (
"spawn_and_kill",
1498 check_spawn_and_kill,