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