00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "dbus-spawn.h"
00025 #include "dbus-sysdeps.h"
00026 #include "dbus-internals.h"
00027 #include "dbus-test.h"
00028 #include "dbus-protocol.h"
00029
00030 #include <unistd.h>
00031 #include <fcntl.h>
00032 #include <signal.h>
00033 #include <sys/wait.h>
00034 #include <errno.h>
00035 #include <stdlib.h>
00036
00042
00043
00044
00045
00046
00050 typedef enum
00051 {
00052 READ_STATUS_OK,
00053 READ_STATUS_ERROR,
00054 READ_STATUS_EOF
00055 } ReadStatus;
00056
00057 static ReadStatus
00058 read_ints (int fd,
00059 int *buf,
00060 int n_ints_in_buf,
00061 int *n_ints_read,
00062 DBusError *error)
00063 {
00064 size_t bytes = 0;
00065 ReadStatus retval;
00066
00067 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00068
00069 retval = READ_STATUS_OK;
00070
00071 while (TRUE)
00072 {
00073 ssize_t chunk;
00074 size_t to_read;
00075
00076 to_read = sizeof (int) * n_ints_in_buf - bytes;
00077
00078 if (to_read == 0)
00079 break;
00080
00081 again:
00082
00083 chunk = read (fd,
00084 ((char*)buf) + bytes,
00085 to_read);
00086
00087 if (chunk < 0 && errno == EINTR)
00088 goto again;
00089
00090 if (chunk < 0)
00091 {
00092 dbus_set_error (error,
00093 DBUS_ERROR_SPAWN_FAILED,
00094 "Failed to read from child pipe (%s)",
00095 _dbus_strerror (errno));
00096
00097 retval = READ_STATUS_ERROR;
00098 break;
00099 }
00100 else if (chunk == 0)
00101 {
00102 retval = READ_STATUS_EOF;
00103 break;
00104 }
00105 else
00106 bytes += chunk;
00107 }
00108
00109 *n_ints_read = (int)(bytes / sizeof(int));
00110
00111 return retval;
00112 }
00113
00114 static ReadStatus
00115 read_pid (int fd,
00116 pid_t *buf,
00117 DBusError *error)
00118 {
00119 size_t bytes = 0;
00120 ReadStatus retval;
00121
00122 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00123
00124 retval = READ_STATUS_OK;
00125
00126 while (TRUE)
00127 {
00128 ssize_t chunk;
00129 size_t to_read;
00130
00131 to_read = sizeof (pid_t) - bytes;
00132
00133 if (to_read == 0)
00134 break;
00135
00136 again:
00137
00138 chunk = read (fd,
00139 ((char*)buf) + bytes,
00140 to_read);
00141 if (chunk < 0 && errno == EINTR)
00142 goto again;
00143
00144 if (chunk < 0)
00145 {
00146 dbus_set_error (error,
00147 DBUS_ERROR_SPAWN_FAILED,
00148 "Failed to read from child pipe (%s)",
00149 _dbus_strerror (errno));
00150
00151 retval = READ_STATUS_ERROR;
00152 break;
00153 }
00154 else if (chunk == 0)
00155 {
00156 retval = READ_STATUS_EOF;
00157 break;
00158 }
00159 else
00160 bytes += chunk;
00161 }
00162
00163 return retval;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 enum
00174 {
00175 CHILD_EXITED,
00176 CHILD_FORK_FAILED,
00177 CHILD_EXEC_FAILED,
00178 CHILD_PID
00179 };
00180
00184 struct DBusBabysitter
00185 {
00186 int refcount;
00188 char *executable;
00190 int socket_to_babysitter;
00191 int error_pipe_from_child;
00193 pid_t sitter_pid;
00194 pid_t grandchild_pid;
00196 DBusWatchList *watches;
00198 DBusWatch *error_watch;
00199 DBusWatch *sitter_watch;
00201 int errnum;
00202 int status;
00203 unsigned int have_child_status : 1;
00204 unsigned int have_fork_errnum : 1;
00205 unsigned int have_exec_errnum : 1;
00206 };
00207
00208 static DBusBabysitter*
00209 _dbus_babysitter_new (void)
00210 {
00211 DBusBabysitter *sitter;
00212
00213 sitter = dbus_new0 (DBusBabysitter, 1);
00214 if (sitter == NULL)
00215 return NULL;
00216
00217 sitter->refcount = 1;
00218
00219 sitter->socket_to_babysitter = -1;
00220 sitter->error_pipe_from_child = -1;
00221
00222 sitter->sitter_pid = -1;
00223 sitter->grandchild_pid = -1;
00224
00225 sitter->watches = _dbus_watch_list_new ();
00226 if (sitter->watches == NULL)
00227 goto failed;
00228
00229 return sitter;
00230
00231 failed:
00232 _dbus_babysitter_unref (sitter);
00233 return NULL;
00234 }
00235
00242 DBusBabysitter *
00243 _dbus_babysitter_ref (DBusBabysitter *sitter)
00244 {
00245 _dbus_assert (sitter != NULL);
00246 _dbus_assert (sitter->refcount > 0);
00247
00248 sitter->refcount += 1;
00249
00250 return sitter;
00251 }
00252
00261 void
00262 _dbus_babysitter_unref (DBusBabysitter *sitter)
00263 {
00264 _dbus_assert (sitter != NULL);
00265 _dbus_assert (sitter->refcount > 0);
00266
00267 sitter->refcount -= 1;
00268 if (sitter->refcount == 0)
00269 {
00270 if (sitter->socket_to_babysitter >= 0)
00271 {
00272
00273
00274
00275
00276
00277
00278
00279 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
00280 sitter->socket_to_babysitter = -1;
00281 }
00282
00283 if (sitter->error_pipe_from_child >= 0)
00284 {
00285 _dbus_close_socket (sitter->error_pipe_from_child, NULL);
00286 sitter->error_pipe_from_child = -1;
00287 }
00288
00289 if (sitter->sitter_pid > 0)
00290 {
00291 int status;
00292 int ret;
00293
00294
00295
00296
00297
00298 ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
00299
00300
00301
00302
00303 if (ret == 0)
00304 kill (sitter->sitter_pid, SIGKILL);
00305
00306 again:
00307 if (ret == 0)
00308 ret = waitpid (sitter->sitter_pid, &status, 0);
00309
00310 if (ret < 0)
00311 {
00312 if (errno == EINTR)
00313 goto again;
00314 else if (errno == ECHILD)
00315 _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
00316 else
00317 _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
00318 errno, _dbus_strerror (errno));
00319 }
00320 else
00321 {
00322 _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
00323 (long) ret, (long) sitter->sitter_pid);
00324
00325 if (WIFEXITED (sitter->status))
00326 _dbus_verbose ("Babysitter exited with status %d\n",
00327 WEXITSTATUS (sitter->status));
00328 else if (WIFSIGNALED (sitter->status))
00329 _dbus_verbose ("Babysitter received signal %d\n",
00330 WTERMSIG (sitter->status));
00331 else
00332 _dbus_verbose ("Babysitter exited abnormally\n");
00333 }
00334
00335 sitter->sitter_pid = -1;
00336 }
00337
00338 if (sitter->error_watch)
00339 {
00340 _dbus_watch_invalidate (sitter->error_watch);
00341 _dbus_watch_unref (sitter->error_watch);
00342 sitter->error_watch = NULL;
00343 }
00344
00345 if (sitter->sitter_watch)
00346 {
00347 _dbus_watch_invalidate (sitter->sitter_watch);
00348 _dbus_watch_unref (sitter->sitter_watch);
00349 sitter->sitter_watch = NULL;
00350 }
00351
00352 if (sitter->watches)
00353 _dbus_watch_list_free (sitter->watches);
00354
00355 dbus_free (sitter->executable);
00356
00357 dbus_free (sitter);
00358 }
00359 }
00360
00361 static ReadStatus
00362 read_data (DBusBabysitter *sitter,
00363 int fd)
00364 {
00365 int what;
00366 int got;
00367 DBusError error;
00368 ReadStatus r;
00369
00370 dbus_error_init (&error);
00371
00372 r = read_ints (fd, &what, 1, &got, &error);
00373
00374 switch (r)
00375 {
00376 case READ_STATUS_ERROR:
00377 _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
00378 dbus_error_free (&error);
00379 return r;
00380
00381 case READ_STATUS_EOF:
00382 return r;
00383
00384 case READ_STATUS_OK:
00385 break;
00386 }
00387
00388 if (got == 1)
00389 {
00390 switch (what)
00391 {
00392 case CHILD_EXITED:
00393 case CHILD_FORK_FAILED:
00394 case CHILD_EXEC_FAILED:
00395 {
00396 int arg;
00397
00398 r = read_ints (fd, &arg, 1, &got, &error);
00399
00400 switch (r)
00401 {
00402 case READ_STATUS_ERROR:
00403 _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
00404 dbus_error_free (&error);
00405 return r;
00406 case READ_STATUS_EOF:
00407 return r;
00408 case READ_STATUS_OK:
00409 break;
00410 }
00411
00412 if (got == 1)
00413 {
00414 if (what == CHILD_EXITED)
00415 {
00416 sitter->have_child_status = TRUE;
00417 sitter->status = arg;
00418 _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
00419 WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
00420 WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
00421 }
00422 else if (what == CHILD_FORK_FAILED)
00423 {
00424 sitter->have_fork_errnum = TRUE;
00425 sitter->errnum = arg;
00426 _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
00427 }
00428 else if (what == CHILD_EXEC_FAILED)
00429 {
00430 sitter->have_exec_errnum = TRUE;
00431 sitter->errnum = arg;
00432 _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
00433 }
00434 }
00435 }
00436 break;
00437 case CHILD_PID:
00438 {
00439 pid_t pid = -1;
00440
00441 r = read_pid (fd, &pid, &error);
00442
00443 switch (r)
00444 {
00445 case READ_STATUS_ERROR:
00446 _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
00447 dbus_error_free (&error);
00448 return r;
00449 case READ_STATUS_EOF:
00450 return r;
00451 case READ_STATUS_OK:
00452 break;
00453 }
00454
00455 sitter->grandchild_pid = pid;
00456
00457 _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
00458 }
00459 break;
00460 default:
00461 _dbus_warn ("Unknown message received from babysitter process\n");
00462 break;
00463 }
00464 }
00465
00466 return r;
00467 }
00468
00469 static void
00470 close_socket_to_babysitter (DBusBabysitter *sitter)
00471 {
00472 _dbus_verbose ("Closing babysitter\n");
00473 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
00474 sitter->socket_to_babysitter = -1;
00475 }
00476
00477 static void
00478 close_error_pipe_from_child (DBusBabysitter *sitter)
00479 {
00480 _dbus_verbose ("Closing child error\n");
00481 _dbus_close_socket (sitter->error_pipe_from_child, NULL);
00482 sitter->error_pipe_from_child = -1;
00483 }
00484
00485 static void
00486 handle_babysitter_socket (DBusBabysitter *sitter,
00487 int revents)
00488 {
00489
00490
00491
00492
00493 if (revents & _DBUS_POLLIN)
00494 {
00495 _dbus_verbose ("Reading data from babysitter\n");
00496 if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK)
00497 close_socket_to_babysitter (sitter);
00498 }
00499 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00500 {
00501 close_socket_to_babysitter (sitter);
00502 }
00503 }
00504
00505 static void
00506 handle_error_pipe (DBusBabysitter *sitter,
00507 int revents)
00508 {
00509 if (revents & _DBUS_POLLIN)
00510 {
00511 _dbus_verbose ("Reading data from child error\n");
00512 if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
00513 close_error_pipe_from_child (sitter);
00514 }
00515 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00516 {
00517 close_error_pipe_from_child (sitter);
00518 }
00519 }
00520
00521
00522 static dbus_bool_t
00523 babysitter_iteration (DBusBabysitter *sitter,
00524 dbus_bool_t block)
00525 {
00526 DBusPollFD fds[2];
00527 int i;
00528 dbus_bool_t descriptors_ready;
00529
00530 descriptors_ready = FALSE;
00531
00532 i = 0;
00533
00534 if (sitter->error_pipe_from_child >= 0)
00535 {
00536 fds[i].fd = sitter->error_pipe_from_child;
00537 fds[i].events = _DBUS_POLLIN;
00538 fds[i].revents = 0;
00539 ++i;
00540 }
00541
00542 if (sitter->socket_to_babysitter >= 0)
00543 {
00544 fds[i].fd = sitter->socket_to_babysitter;
00545 fds[i].events = _DBUS_POLLIN;
00546 fds[i].revents = 0;
00547 ++i;
00548 }
00549
00550 if (i > 0)
00551 {
00552 int ret;
00553
00554 do
00555 {
00556 ret = _dbus_poll (fds, i, 0);
00557 }
00558 while (ret < 0 && errno == EINTR);
00559
00560 if (ret == 0 && block)
00561 {
00562 do
00563 {
00564 ret = _dbus_poll (fds, i, -1);
00565 }
00566 while (ret < 0 && errno == EINTR);
00567 }
00568
00569 if (ret > 0)
00570 {
00571 descriptors_ready = TRUE;
00572
00573 while (i > 0)
00574 {
00575 --i;
00576 if (fds[i].fd == sitter->error_pipe_from_child)
00577 handle_error_pipe (sitter, fds[i].revents);
00578 else if (fds[i].fd == sitter->socket_to_babysitter)
00579 handle_babysitter_socket (sitter, fds[i].revents);
00580 }
00581 }
00582 }
00583
00584 return descriptors_ready;
00585 }
00586
00591 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
00592
00599 void
00600 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
00601 {
00602
00603 while (LIVE_CHILDREN (sitter) &&
00604 sitter->grandchild_pid == -1)
00605 babysitter_iteration (sitter, TRUE);
00606
00607 _dbus_verbose ("Got child PID %ld for killing\n",
00608 (long) sitter->grandchild_pid);
00609
00610 if (sitter->grandchild_pid == -1)
00611 return;
00612
00613 kill (sitter->grandchild_pid, SIGKILL);
00614 }
00615
00621 dbus_bool_t
00622 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
00623 {
00624
00625
00626 while (LIVE_CHILDREN (sitter) &&
00627 babysitter_iteration (sitter, FALSE))
00628 ;
00629
00630
00631 return sitter->socket_to_babysitter < 0;
00632 }
00633
00643 void
00644 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
00645 DBusError *error)
00646 {
00647 if (!_dbus_babysitter_get_child_exited (sitter))
00648 return;
00649
00650
00651
00652
00653
00654 if (sitter->have_exec_errnum)
00655 {
00656 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
00657 "Failed to execute program %s: %s",
00658 sitter->executable, _dbus_strerror (sitter->errnum));
00659 }
00660 else if (sitter->have_fork_errnum)
00661 {
00662 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00663 "Failed to fork a new process %s: %s",
00664 sitter->executable, _dbus_strerror (sitter->errnum));
00665 }
00666 else if (sitter->have_child_status)
00667 {
00668 if (WIFEXITED (sitter->status))
00669 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
00670 "Process %s exited with status %d",
00671 sitter->executable, WEXITSTATUS (sitter->status));
00672 else if (WIFSIGNALED (sitter->status))
00673 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
00674 "Process %s received signal %d",
00675 sitter->executable, WTERMSIG (sitter->status));
00676 else
00677 dbus_set_error (error, DBUS_ERROR_FAILED,
00678 "Process %s exited abnormally",
00679 sitter->executable);
00680 }
00681 else
00682 {
00683 dbus_set_error (error, DBUS_ERROR_FAILED,
00684 "Process %s exited, reason unknown",
00685 sitter->executable);
00686 }
00687 }
00688
00701 dbus_bool_t
00702 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
00703 DBusAddWatchFunction add_function,
00704 DBusRemoveWatchFunction remove_function,
00705 DBusWatchToggledFunction toggled_function,
00706 void *data,
00707 DBusFreeFunction free_data_function)
00708 {
00709 return _dbus_watch_list_set_functions (sitter->watches,
00710 add_function,
00711 remove_function,
00712 toggled_function,
00713 data,
00714 free_data_function);
00715 }
00716
00717 static dbus_bool_t
00718 handle_watch (DBusWatch *watch,
00719 unsigned int condition,
00720 void *data)
00721 {
00722 DBusBabysitter *sitter = data;
00723 int revents;
00724 int fd;
00725
00726 revents = 0;
00727 if (condition & DBUS_WATCH_READABLE)
00728 revents |= _DBUS_POLLIN;
00729 if (condition & DBUS_WATCH_ERROR)
00730 revents |= _DBUS_POLLERR;
00731 if (condition & DBUS_WATCH_HANGUP)
00732 revents |= _DBUS_POLLHUP;
00733
00734 fd = dbus_watch_get_fd (watch);
00735
00736 if (fd == sitter->error_pipe_from_child)
00737 handle_error_pipe (sitter, revents);
00738 else if (fd == sitter->socket_to_babysitter)
00739 handle_babysitter_socket (sitter, revents);
00740
00741 while (LIVE_CHILDREN (sitter) &&
00742 babysitter_iteration (sitter, FALSE))
00743 ;
00744
00745 return TRUE;
00746 }
00747
00749 #define READ_END 0
00750
00751 #define WRITE_END 1
00752
00753
00754
00755
00756
00757
00758 static int
00759 close_and_invalidate (int *fd)
00760 {
00761 int ret;
00762
00763 if (*fd < 0)
00764 return -1;
00765 else
00766 {
00767 ret = _dbus_close_socket (*fd, NULL);
00768 *fd = -1;
00769 }
00770
00771 return ret;
00772 }
00773
00774 static dbus_bool_t
00775 make_pipe (int p[2],
00776 DBusError *error)
00777 {
00778 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00779
00780 if (pipe (p) < 0)
00781 {
00782 dbus_set_error (error,
00783 DBUS_ERROR_SPAWN_FAILED,
00784 "Failed to create pipe for communicating with child process (%s)",
00785 _dbus_strerror (errno));
00786 return FALSE;
00787 }
00788
00789 return TRUE;
00790 }
00791
00792 static void
00793 do_write (int fd, const void *buf, size_t count)
00794 {
00795 size_t bytes_written;
00796 int ret;
00797
00798 bytes_written = 0;
00799
00800 again:
00801
00802 ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
00803
00804 if (ret < 0)
00805 {
00806 if (errno == EINTR)
00807 goto again;
00808 else
00809 {
00810 _dbus_warn ("Failed to write data to pipe!\n");
00811 exit (1);
00812 }
00813 }
00814 else
00815 bytes_written += ret;
00816
00817 if (bytes_written < count)
00818 goto again;
00819 }
00820
00821 static void
00822 write_err_and_exit (int fd, int msg)
00823 {
00824 int en = errno;
00825
00826 do_write (fd, &msg, sizeof (msg));
00827 do_write (fd, &en, sizeof (en));
00828
00829 exit (1);
00830 }
00831
00832 static void
00833 write_pid (int fd, pid_t pid)
00834 {
00835 int msg = CHILD_PID;
00836
00837 do_write (fd, &msg, sizeof (msg));
00838 do_write (fd, &pid, sizeof (pid));
00839 }
00840
00841 static void
00842 write_status_and_exit (int fd, int status)
00843 {
00844 int msg = CHILD_EXITED;
00845
00846 do_write (fd, &msg, sizeof (msg));
00847 do_write (fd, &status, sizeof (status));
00848
00849 exit (0);
00850 }
00851
00852 static void
00853 do_exec (int child_err_report_fd,
00854 char **argv,
00855 DBusSpawnChildSetupFunc child_setup,
00856 void *user_data)
00857 {
00858 #ifdef DBUS_BUILD_TESTS
00859 int i, max_open;
00860 #endif
00861
00862 int oom = open ("/proc/self/oom_adj", O_WRONLY|O_SYNC);
00863 if (oom >= 0)
00864 {
00865 write (oom, "0", sizeof (char));
00866 _dbus_close (oom, NULL);
00867 }
00868
00869 _dbus_verbose_reset ();
00870 _dbus_verbose ("Child process has PID %lu\n",
00871 _dbus_getpid ());
00872
00873 if (child_setup)
00874 (* child_setup) (user_data);
00875
00876 #ifdef DBUS_BUILD_TESTS
00877 max_open = sysconf (_SC_OPEN_MAX);
00878
00879 for (i = 3; i < max_open; i++)
00880 {
00881 int retval;
00882
00883 if (i == child_err_report_fd)
00884 continue;
00885
00886 retval = fcntl (i, F_GETFD);
00887
00888 if (retval != -1 && !(retval & FD_CLOEXEC))
00889 _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
00890 }
00891 #endif
00892
00893 execv (argv[0], argv);
00894
00895
00896 write_err_and_exit (child_err_report_fd,
00897 CHILD_EXEC_FAILED);
00898 }
00899
00900 static void
00901 check_babysit_events (pid_t grandchild_pid,
00902 int parent_pipe,
00903 int revents)
00904 {
00905 pid_t ret;
00906 int status;
00907
00908 do
00909 {
00910 ret = waitpid (grandchild_pid, &status, WNOHANG);
00911
00912
00913
00914 }
00915 while (ret < 0 && errno == EINTR);
00916
00917 if (ret == 0)
00918 {
00919 _dbus_verbose ("no child exited\n");
00920
00921 ;
00922 }
00923 else if (ret < 0)
00924 {
00925
00926 _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
00927 _dbus_strerror (errno));
00928 exit (1);
00929 }
00930 else if (ret == grandchild_pid)
00931 {
00932
00933 _dbus_verbose ("reaped child pid %ld\n", (long) ret);
00934
00935 write_status_and_exit (parent_pipe, status);
00936 }
00937 else
00938 {
00939 _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
00940 (int) ret);
00941 exit (1);
00942 }
00943
00944 if (revents & _DBUS_POLLIN)
00945 {
00946 _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
00947 }
00948
00949 if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00950 {
00951
00952 _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
00953 exit (0);
00954 }
00955 }
00956
00957 static int babysit_sigchld_pipe = -1;
00958
00959 static void
00960 babysit_signal_handler (int signo)
00961 {
00962 char b = '\0';
00963 again:
00964 write (babysit_sigchld_pipe, &b, 1);
00965 if (errno == EINTR)
00966 goto again;
00967 }
00968
00969 static void
00970 babysit (pid_t grandchild_pid,
00971 int parent_pipe)
00972 {
00973 int sigchld_pipe[2];
00974
00975
00976
00977
00978 _dbus_verbose_reset ();
00979
00980
00981
00982
00983
00984
00985 if (pipe (sigchld_pipe) < 0)
00986 {
00987 _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
00988 exit (1);
00989 }
00990
00991 babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
00992
00993 _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
00994
00995 write_pid (parent_pipe, grandchild_pid);
00996
00997 check_babysit_events (grandchild_pid, parent_pipe, 0);
00998
00999 while (TRUE)
01000 {
01001 DBusPollFD pfds[2];
01002
01003 pfds[0].fd = parent_pipe;
01004 pfds[0].events = _DBUS_POLLIN;
01005 pfds[0].revents = 0;
01006
01007 pfds[1].fd = sigchld_pipe[READ_END];
01008 pfds[1].events = _DBUS_POLLIN;
01009 pfds[1].revents = 0;
01010
01011 if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
01012 {
01013 _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
01014 exit (1);
01015 }
01016
01017 if (pfds[0].revents != 0)
01018 {
01019 check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
01020 }
01021 else if (pfds[1].revents & _DBUS_POLLIN)
01022 {
01023 char b;
01024 read (sigchld_pipe[READ_END], &b, 1);
01025
01026 check_babysit_events (grandchild_pid, parent_pipe, 0);
01027 }
01028 }
01029
01030 exit (1);
01031 }
01032
01051 dbus_bool_t
01052 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
01053 char **argv,
01054 DBusSpawnChildSetupFunc child_setup,
01055 void *user_data,
01056 DBusError *error)
01057 {
01058 DBusBabysitter *sitter;
01059 int child_err_report_pipe[2] = { -1, -1 };
01060 int babysitter_pipe[2] = { -1, -1 };
01061 pid_t pid;
01062
01063 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01064
01065 if (sitter_p != NULL)
01066 *sitter_p = NULL;
01067
01068 sitter = NULL;
01069
01070 sitter = _dbus_babysitter_new ();
01071 if (sitter == NULL)
01072 {
01073 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01074 return FALSE;
01075 }
01076
01077 sitter->executable = _dbus_strdup (argv[0]);
01078 if (sitter->executable == NULL)
01079 {
01080 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01081 goto cleanup_and_fail;
01082 }
01083
01084 if (!make_pipe (child_err_report_pipe, error))
01085 goto cleanup_and_fail;
01086
01087 _dbus_fd_set_close_on_exec (child_err_report_pipe[READ_END]);
01088 _dbus_fd_set_close_on_exec (child_err_report_pipe[WRITE_END]);
01089
01090 if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
01091 goto cleanup_and_fail;
01092
01093 _dbus_fd_set_close_on_exec (babysitter_pipe[0]);
01094 _dbus_fd_set_close_on_exec (babysitter_pipe[1]);
01095
01096
01097
01098
01099
01100
01101 sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
01102 DBUS_WATCH_READABLE,
01103 TRUE, handle_watch, sitter, NULL);
01104 if (sitter->error_watch == NULL)
01105 {
01106 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01107 goto cleanup_and_fail;
01108 }
01109
01110 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch))
01111 {
01112 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01113 goto cleanup_and_fail;
01114 }
01115
01116 sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0],
01117 DBUS_WATCH_READABLE,
01118 TRUE, handle_watch, sitter, NULL);
01119 if (sitter->sitter_watch == NULL)
01120 {
01121 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01122 goto cleanup_and_fail;
01123 }
01124
01125 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
01126 {
01127 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01128 goto cleanup_and_fail;
01129 }
01130
01131 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01132
01133 pid = fork ();
01134
01135 if (pid < 0)
01136 {
01137 dbus_set_error (error,
01138 DBUS_ERROR_SPAWN_FORK_FAILED,
01139 "Failed to fork (%s)",
01140 _dbus_strerror (errno));
01141 goto cleanup_and_fail;
01142 }
01143 else if (pid == 0)
01144 {
01145
01146 int grandchild_pid;
01147
01148
01149
01150
01151 signal (SIGPIPE, SIG_DFL);
01152
01153
01154 close_and_invalidate (&child_err_report_pipe[READ_END]);
01155 close_and_invalidate (&babysitter_pipe[0]);
01156
01157
01158 grandchild_pid = fork ();
01159
01160 if (grandchild_pid < 0)
01161 {
01162 write_err_and_exit (babysitter_pipe[1],
01163 CHILD_FORK_FAILED);
01164 _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
01165 }
01166 else if (grandchild_pid == 0)
01167 {
01168 int p;
01169
01170
01171 if (setsid () == -1)
01172 _dbus_warn ("setsid() failed: %s\n", _dbus_strerror (errno));
01173 errno = 0;
01174 p = getpriority(PRIO_PROCESS, 0);
01175 if (!errno && p < 0) {
01176 setpriority(PRIO_PROCESS, 0, 0);
01177 }
01178 do_exec (child_err_report_pipe[WRITE_END],
01179 argv,
01180 child_setup, user_data);
01181 _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
01182 }
01183 else
01184 {
01185 babysit (grandchild_pid, babysitter_pipe[1]);
01186 _dbus_assert_not_reached ("Got to code after babysit()");
01187 }
01188 }
01189 else
01190 {
01191
01192 close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01193 close_and_invalidate (&babysitter_pipe[1]);
01194
01195 sitter->socket_to_babysitter = babysitter_pipe[0];
01196 babysitter_pipe[0] = -1;
01197
01198 sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
01199 child_err_report_pipe[READ_END] = -1;
01200
01201 sitter->sitter_pid = pid;
01202
01203 if (sitter_p != NULL)
01204 *sitter_p = sitter;
01205 else
01206 _dbus_babysitter_unref (sitter);
01207
01208 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01209
01210 return TRUE;
01211 }
01212
01213 cleanup_and_fail:
01214
01215 _DBUS_ASSERT_ERROR_IS_SET (error);
01216
01217 close_and_invalidate (&child_err_report_pipe[READ_END]);
01218 close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01219 close_and_invalidate (&babysitter_pipe[0]);
01220 close_and_invalidate (&babysitter_pipe[1]);
01221
01222 if (sitter != NULL)
01223 _dbus_babysitter_unref (sitter);
01224
01225 return FALSE;
01226 }
01227
01230 #ifdef DBUS_BUILD_TESTS
01231
01232 static void
01233 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
01234 {
01235 while (LIVE_CHILDREN (sitter))
01236 babysitter_iteration (sitter, TRUE);
01237 }
01238
01239 static dbus_bool_t
01240 check_spawn_nonexistent (void *data)
01241 {
01242 char *argv[4] = { NULL, NULL, NULL, NULL };
01243 DBusBabysitter *sitter;
01244 DBusError error;
01245
01246 sitter = NULL;
01247
01248 dbus_error_init (&error);
01249
01250
01251
01252 argv[0] = "/this/does/not/exist/32542sdgafgafdg";
01253 if (_dbus_spawn_async_with_babysitter (&sitter, argv,
01254 NULL, NULL,
01255 &error))
01256 {
01257 _dbus_babysitter_block_for_child_exit (sitter);
01258 _dbus_babysitter_set_child_exit_error (sitter, &error);
01259 }
01260
01261 if (sitter)
01262 _dbus_babysitter_unref (sitter);
01263
01264 if (!dbus_error_is_set (&error))
01265 {
01266 _dbus_warn ("Did not get an error launching nonexistent executable\n");
01267 return FALSE;
01268 }
01269
01270 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01271 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
01272 {
01273 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
01274 error.name, error.message);
01275 dbus_error_free (&error);
01276 return FALSE;
01277 }
01278
01279 dbus_error_free (&error);
01280
01281 return TRUE;
01282 }
01283
01284 static dbus_bool_t
01285 check_spawn_segfault (void *data)
01286 {
01287 char *argv[4] = { NULL, NULL, NULL, NULL };
01288 DBusBabysitter *sitter;
01289 DBusError error;
01290
01291 sitter = NULL;
01292
01293 dbus_error_init (&error);
01294
01295
01296
01297 argv[0] = TEST_SEGFAULT_BINARY;
01298 if (_dbus_spawn_async_with_babysitter (&sitter, argv,
01299 NULL, NULL,
01300 &error))
01301 {
01302 _dbus_babysitter_block_for_child_exit (sitter);
01303 _dbus_babysitter_set_child_exit_error (sitter, &error);
01304 }
01305
01306 if (sitter)
01307 _dbus_babysitter_unref (sitter);
01308
01309 if (!dbus_error_is_set (&error))
01310 {
01311 _dbus_warn ("Did not get an error launching segfaulting binary\n");
01312 return FALSE;
01313 }
01314
01315 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01316 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01317 {
01318 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
01319 error.name, error.message);
01320 dbus_error_free (&error);
01321 return FALSE;
01322 }
01323
01324 dbus_error_free (&error);
01325
01326 return TRUE;
01327 }
01328
01329 static dbus_bool_t
01330 check_spawn_exit (void *data)
01331 {
01332 char *argv[4] = { NULL, NULL, NULL, NULL };
01333 DBusBabysitter *sitter;
01334 DBusError error;
01335
01336 sitter = NULL;
01337
01338 dbus_error_init (&error);
01339
01340
01341
01342 argv[0] = TEST_EXIT_BINARY;
01343 if (_dbus_spawn_async_with_babysitter (&sitter, argv,
01344 NULL, NULL,
01345 &error))
01346 {
01347 _dbus_babysitter_block_for_child_exit (sitter);
01348 _dbus_babysitter_set_child_exit_error (sitter, &error);
01349 }
01350
01351 if (sitter)
01352 _dbus_babysitter_unref (sitter);
01353
01354 if (!dbus_error_is_set (&error))
01355 {
01356 _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
01357 return FALSE;
01358 }
01359
01360 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01361 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
01362 {
01363 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
01364 error.name, error.message);
01365 dbus_error_free (&error);
01366 return FALSE;
01367 }
01368
01369 dbus_error_free (&error);
01370
01371 return TRUE;
01372 }
01373
01374 static dbus_bool_t
01375 check_spawn_and_kill (void *data)
01376 {
01377 char *argv[4] = { NULL, NULL, NULL, NULL };
01378 DBusBabysitter *sitter;
01379 DBusError error;
01380
01381 sitter = NULL;
01382
01383 dbus_error_init (&error);
01384
01385
01386
01387 argv[0] = TEST_SLEEP_FOREVER_BINARY;
01388 if (_dbus_spawn_async_with_babysitter (&sitter, argv,
01389 NULL, NULL,
01390 &error))
01391 {
01392 _dbus_babysitter_kill_child (sitter);
01393
01394 _dbus_babysitter_block_for_child_exit (sitter);
01395
01396 _dbus_babysitter_set_child_exit_error (sitter, &error);
01397 }
01398
01399 if (sitter)
01400 _dbus_babysitter_unref (sitter);
01401
01402 if (!dbus_error_is_set (&error))
01403 {
01404 _dbus_warn ("Did not get an error after killing spawned binary\n");
01405 return FALSE;
01406 }
01407
01408 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01409 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01410 {
01411 _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
01412 error.name, error.message);
01413 dbus_error_free (&error);
01414 return FALSE;
01415 }
01416
01417 dbus_error_free (&error);
01418
01419 return TRUE;
01420 }
01421
01422 dbus_bool_t
01423 _dbus_spawn_test (const char *test_data_dir)
01424 {
01425 if (!_dbus_test_oom_handling ("spawn_nonexistent",
01426 check_spawn_nonexistent,
01427 NULL))
01428 return FALSE;
01429
01430 if (!_dbus_test_oom_handling ("spawn_segfault",
01431 check_spawn_segfault,
01432 NULL))
01433 return FALSE;
01434
01435 if (!_dbus_test_oom_handling ("spawn_exit",
01436 check_spawn_exit,
01437 NULL))
01438 return FALSE;
01439
01440 if (!_dbus_test_oom_handling ("spawn_and_kill",
01441 check_spawn_and_kill,
01442 NULL))
01443 return FALSE;
01444
01445 return TRUE;
01446 }
01447 #endif