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
00039 extern char **environ;
00040
00046
00047
00048
00049
00050
00054 typedef enum
00055 {
00056 READ_STATUS_OK,
00057 READ_STATUS_ERROR,
00058 READ_STATUS_EOF
00059 } ReadStatus;
00060
00061 static ReadStatus
00062 read_ints (int fd,
00063 int *buf,
00064 int n_ints_in_buf,
00065 int *n_ints_read,
00066 DBusError *error)
00067 {
00068 size_t bytes = 0;
00069 ReadStatus retval;
00070
00071 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00072
00073 retval = READ_STATUS_OK;
00074
00075 while (TRUE)
00076 {
00077 size_t chunk;
00078 ssize_t to_read;
00079
00080 to_read = sizeof (int) * n_ints_in_buf - bytes;
00081
00082 if (to_read == 0)
00083 break;
00084
00085 again:
00086
00087 chunk = read (fd,
00088 ((char*)buf) + bytes,
00089 to_read);
00090
00091 if (chunk < 0 && errno == EINTR)
00092 goto again;
00093
00094 if (chunk < 0)
00095 {
00096 dbus_set_error (error,
00097 DBUS_ERROR_SPAWN_FAILED,
00098 "Failed to read from child pipe (%s)",
00099 _dbus_strerror (errno));
00100
00101 retval = READ_STATUS_ERROR;
00102 break;
00103 }
00104 else if (chunk == 0)
00105 {
00106 retval = READ_STATUS_EOF;
00107 break;
00108 }
00109 else
00110 bytes += chunk;
00111 }
00112
00113 *n_ints_read = (int)(bytes / sizeof(int));
00114
00115 return retval;
00116 }
00117
00118 static ReadStatus
00119 read_pid (int fd,
00120 pid_t *buf,
00121 DBusError *error)
00122 {
00123 size_t bytes = 0;
00124 ReadStatus retval;
00125
00126 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00127
00128 retval = READ_STATUS_OK;
00129
00130 while (TRUE)
00131 {
00132 size_t chunk;
00133 ssize_t to_read;
00134
00135 to_read = sizeof (pid_t) - bytes;
00136
00137 if (to_read == 0)
00138 break;
00139
00140 again:
00141
00142 chunk = read (fd,
00143 ((char*)buf) + bytes,
00144 to_read);
00145 if (chunk < 0 && errno == EINTR)
00146 goto again;
00147
00148 if (chunk < 0)
00149 {
00150 dbus_set_error (error,
00151 DBUS_ERROR_SPAWN_FAILED,
00152 "Failed to read from child pipe (%s)",
00153 _dbus_strerror (errno));
00154
00155 retval = READ_STATUS_ERROR;
00156 break;
00157 }
00158 else if (chunk == 0)
00159 {
00160 retval = READ_STATUS_EOF;
00161 break;
00162 }
00163 else
00164 bytes += chunk;
00165 }
00166
00167 return retval;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177 enum
00178 {
00179 CHILD_EXITED,
00180 CHILD_FORK_FAILED,
00181 CHILD_EXEC_FAILED,
00182 CHILD_PID
00183 };
00184
00188 struct DBusBabysitter
00189 {
00190 int refcount;
00192 char *executable;
00194 int socket_to_babysitter;
00195 int error_pipe_from_child;
00197 pid_t sitter_pid;
00198 pid_t grandchild_pid;
00200 DBusWatchList *watches;
00202 DBusWatch *error_watch;
00203 DBusWatch *sitter_watch;
00205 int errnum;
00206 int status;
00207 unsigned int have_child_status : 1;
00208 unsigned int have_fork_errnum : 1;
00209 unsigned int have_exec_errnum : 1;
00210 };
00211
00212 static DBusBabysitter*
00213 _dbus_babysitter_new (void)
00214 {
00215 DBusBabysitter *sitter;
00216
00217 sitter = dbus_new0 (DBusBabysitter, 1);
00218 if (sitter == NULL)
00219 return NULL;
00220
00221 sitter->refcount = 1;
00222
00223 sitter->socket_to_babysitter = -1;
00224 sitter->error_pipe_from_child = -1;
00225
00226 sitter->sitter_pid = -1;
00227 sitter->grandchild_pid = -1;
00228
00229 sitter->watches = _dbus_watch_list_new ();
00230 if (sitter->watches == NULL)
00231 goto failed;
00232
00233 return sitter;
00234
00235 failed:
00236 _dbus_babysitter_unref (sitter);
00237 return NULL;
00238 }
00239
00246 DBusBabysitter *
00247 _dbus_babysitter_ref (DBusBabysitter *sitter)
00248 {
00249 _dbus_assert (sitter != NULL);
00250 _dbus_assert (sitter->refcount > 0);
00251
00252 sitter->refcount += 1;
00253
00254 return sitter;
00255 }
00256
00265 void
00266 _dbus_babysitter_unref (DBusBabysitter *sitter)
00267 {
00268 _dbus_assert (sitter != NULL);
00269 _dbus_assert (sitter->refcount > 0);
00270
00271 sitter->refcount -= 1;
00272 if (sitter->refcount == 0)
00273 {
00274 if (sitter->socket_to_babysitter >= 0)
00275 {
00276
00277
00278
00279
00280
00281
00282
00283 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
00284 sitter->socket_to_babysitter = -1;
00285 }
00286
00287 if (sitter->error_pipe_from_child >= 0)
00288 {
00289 _dbus_close_socket (sitter->error_pipe_from_child, NULL);
00290 sitter->error_pipe_from_child = -1;
00291 }
00292
00293 if (sitter->sitter_pid > 0)
00294 {
00295 int status;
00296 int ret;
00297
00298
00299
00300
00301
00302 ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
00303
00304
00305
00306
00307 if (ret == 0)
00308 kill (sitter->sitter_pid, SIGKILL);
00309
00310 again:
00311 if (ret == 0)
00312 ret = waitpid (sitter->sitter_pid, &status, 0);
00313
00314 if (ret < 0)
00315 {
00316 if (errno == EINTR)
00317 goto again;
00318 else if (errno == ECHILD)
00319 _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
00320 else
00321 _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
00322 errno, _dbus_strerror (errno));
00323 }
00324 else
00325 {
00326 _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
00327 (long) ret, (long) sitter->sitter_pid);
00328
00329 if (WIFEXITED (sitter->status))
00330 _dbus_verbose ("Babysitter exited with status %d\n",
00331 WEXITSTATUS (sitter->status));
00332 else if (WIFSIGNALED (sitter->status))
00333 _dbus_verbose ("Babysitter received signal %d\n",
00334 WTERMSIG (sitter->status));
00335 else
00336 _dbus_verbose ("Babysitter exited abnormally\n");
00337 }
00338
00339 sitter->sitter_pid = -1;
00340 }
00341
00342 if (sitter->error_watch)
00343 {
00344 _dbus_watch_invalidate (sitter->error_watch);
00345 _dbus_watch_unref (sitter->error_watch);
00346 sitter->error_watch = NULL;
00347 }
00348
00349 if (sitter->sitter_watch)
00350 {
00351 _dbus_watch_invalidate (sitter->sitter_watch);
00352 _dbus_watch_unref (sitter->sitter_watch);
00353 sitter->sitter_watch = NULL;
00354 }
00355
00356 if (sitter->watches)
00357 _dbus_watch_list_free (sitter->watches);
00358
00359 dbus_free (sitter->executable);
00360
00361 dbus_free (sitter);
00362 }
00363 }
00364
00365 static ReadStatus
00366 read_data (DBusBabysitter *sitter,
00367 int fd)
00368 {
00369 int what;
00370 int got;
00371 DBusError error = DBUS_ERROR_INIT;
00372 ReadStatus r;
00373
00374 r = read_ints (fd, &what, 1, &got, &error);
00375
00376 switch (r)
00377 {
00378 case READ_STATUS_ERROR:
00379 _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
00380 dbus_error_free (&error);
00381 return r;
00382
00383 case READ_STATUS_EOF:
00384 return r;
00385
00386 case READ_STATUS_OK:
00387 break;
00388 }
00389
00390 if (got == 1)
00391 {
00392 switch (what)
00393 {
00394 case CHILD_EXITED:
00395 case CHILD_FORK_FAILED:
00396 case CHILD_EXEC_FAILED:
00397 {
00398 int arg;
00399
00400 r = read_ints (fd, &arg, 1, &got, &error);
00401
00402 switch (r)
00403 {
00404 case READ_STATUS_ERROR:
00405 _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
00406 dbus_error_free (&error);
00407 return r;
00408 case READ_STATUS_EOF:
00409 return r;
00410 case READ_STATUS_OK:
00411 break;
00412 }
00413
00414 if (got == 1)
00415 {
00416 if (what == CHILD_EXITED)
00417 {
00418 sitter->have_child_status = TRUE;
00419 sitter->status = arg;
00420 sitter->errnum = 0;
00421 _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
00422 WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
00423 WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
00424 }
00425 else if (what == CHILD_FORK_FAILED)
00426 {
00427 sitter->have_fork_errnum = TRUE;
00428 sitter->errnum = arg;
00429 _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
00430 }
00431 else if (what == CHILD_EXEC_FAILED)
00432 {
00433 sitter->have_exec_errnum = TRUE;
00434 sitter->errnum = arg;
00435 _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
00436 }
00437 }
00438 }
00439 break;
00440 case CHILD_PID:
00441 {
00442 pid_t pid = -1;
00443
00444 r = read_pid (fd, &pid, &error);
00445
00446 switch (r)
00447 {
00448 case READ_STATUS_ERROR:
00449 _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
00450 dbus_error_free (&error);
00451 return r;
00452 case READ_STATUS_EOF:
00453 return r;
00454 case READ_STATUS_OK:
00455 break;
00456 }
00457
00458 sitter->grandchild_pid = pid;
00459
00460 _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
00461 }
00462 break;
00463 default:
00464 _dbus_warn ("Unknown message received from babysitter process\n");
00465 break;
00466 }
00467 }
00468
00469 return r;
00470 }
00471
00472 static void
00473 close_socket_to_babysitter (DBusBabysitter *sitter)
00474 {
00475 _dbus_verbose ("Closing babysitter\n");
00476 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
00477 sitter->socket_to_babysitter = -1;
00478 }
00479
00480 static void
00481 close_error_pipe_from_child (DBusBabysitter *sitter)
00482 {
00483 _dbus_verbose ("Closing child error\n");
00484 _dbus_close_socket (sitter->error_pipe_from_child, NULL);
00485 sitter->error_pipe_from_child = -1;
00486 }
00487
00488 static void
00489 handle_babysitter_socket (DBusBabysitter *sitter,
00490 int revents)
00491 {
00492
00493
00494
00495
00496 if (revents & _DBUS_POLLIN)
00497 {
00498 _dbus_verbose ("Reading data from babysitter\n");
00499 if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK)
00500 close_socket_to_babysitter (sitter);
00501 }
00502 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00503 {
00504 close_socket_to_babysitter (sitter);
00505 }
00506 }
00507
00508 static void
00509 handle_error_pipe (DBusBabysitter *sitter,
00510 int revents)
00511 {
00512 if (revents & _DBUS_POLLIN)
00513 {
00514 _dbus_verbose ("Reading data from child error\n");
00515 if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
00516 close_error_pipe_from_child (sitter);
00517 }
00518 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00519 {
00520 close_error_pipe_from_child (sitter);
00521 }
00522 }
00523
00524
00525 static dbus_bool_t
00526 babysitter_iteration (DBusBabysitter *sitter,
00527 dbus_bool_t block)
00528 {
00529 DBusPollFD fds[2];
00530 int i;
00531 dbus_bool_t descriptors_ready;
00532
00533 descriptors_ready = FALSE;
00534
00535 i = 0;
00536
00537 if (sitter->error_pipe_from_child >= 0)
00538 {
00539 fds[i].fd = sitter->error_pipe_from_child;
00540 fds[i].events = _DBUS_POLLIN;
00541 fds[i].revents = 0;
00542 ++i;
00543 }
00544
00545 if (sitter->socket_to_babysitter >= 0)
00546 {
00547 fds[i].fd = sitter->socket_to_babysitter;
00548 fds[i].events = _DBUS_POLLIN;
00549 fds[i].revents = 0;
00550 ++i;
00551 }
00552
00553 if (i > 0)
00554 {
00555 int ret;
00556
00557 do
00558 {
00559 ret = _dbus_poll (fds, i, 0);
00560 }
00561 while (ret < 0 && errno == EINTR);
00562
00563 if (ret == 0 && block)
00564 {
00565 do
00566 {
00567 ret = _dbus_poll (fds, i, -1);
00568 }
00569 while (ret < 0 && errno == EINTR);
00570 }
00571
00572 if (ret > 0)
00573 {
00574 descriptors_ready = TRUE;
00575
00576 while (i > 0)
00577 {
00578 --i;
00579 if (fds[i].fd == sitter->error_pipe_from_child)
00580 handle_error_pipe (sitter, fds[i].revents);
00581 else if (fds[i].fd == sitter->socket_to_babysitter)
00582 handle_babysitter_socket (sitter, fds[i].revents);
00583 }
00584 }
00585 }
00586
00587 return descriptors_ready;
00588 }
00589
00594 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
00595
00602 void
00603 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
00604 {
00605
00606 while (LIVE_CHILDREN (sitter) &&
00607 sitter->grandchild_pid == -1)
00608 babysitter_iteration (sitter, TRUE);
00609
00610 _dbus_verbose ("Got child PID %ld for killing\n",
00611 (long) sitter->grandchild_pid);
00612
00613 if (sitter->grandchild_pid == -1)
00614 return;
00615
00616 kill (sitter->grandchild_pid, SIGKILL);
00617 }
00618
00624 dbus_bool_t
00625 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
00626 {
00627
00628
00629 while (LIVE_CHILDREN (sitter) &&
00630 babysitter_iteration (sitter, FALSE))
00631 ;
00632
00633
00634 return sitter->socket_to_babysitter < 0;
00635 }
00636
00649 dbus_bool_t
00650 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
00651 int *status)
00652 {
00653 if (!_dbus_babysitter_get_child_exited (sitter))
00654 _dbus_assert_not_reached ("Child has not exited");
00655
00656 if (!sitter->have_child_status ||
00657 !(WIFEXITED (sitter->status)))
00658 return FALSE;
00659
00660 *status = WEXITSTATUS (sitter->status);
00661 return TRUE;
00662 }
00663
00673 void
00674 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
00675 DBusError *error)
00676 {
00677 if (!_dbus_babysitter_get_child_exited (sitter))
00678 return;
00679
00680
00681
00682
00683
00684 if (sitter->have_exec_errnum)
00685 {
00686 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
00687 "Failed to execute program %s: %s",
00688 sitter->executable, _dbus_strerror (sitter->errnum));
00689 }
00690 else if (sitter->have_fork_errnum)
00691 {
00692 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00693 "Failed to fork a new process %s: %s",
00694 sitter->executable, _dbus_strerror (sitter->errnum));
00695 }
00696 else if (sitter->have_child_status)
00697 {
00698 if (WIFEXITED (sitter->status))
00699 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
00700 "Process %s exited with status %d",
00701 sitter->executable, WEXITSTATUS (sitter->status));
00702 else if (WIFSIGNALED (sitter->status))
00703 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
00704 "Process %s received signal %d",
00705 sitter->executable, WTERMSIG (sitter->status));
00706 else
00707 dbus_set_error (error, DBUS_ERROR_FAILED,
00708 "Process %s exited abnormally",
00709 sitter->executable);
00710 }
00711 else
00712 {
00713 dbus_set_error (error, DBUS_ERROR_FAILED,
00714 "Process %s exited, reason unknown",
00715 sitter->executable);
00716 }
00717 }
00718
00731 dbus_bool_t
00732 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
00733 DBusAddWatchFunction add_function,
00734 DBusRemoveWatchFunction remove_function,
00735 DBusWatchToggledFunction toggled_function,
00736 void *data,
00737 DBusFreeFunction free_data_function)
00738 {
00739 return _dbus_watch_list_set_functions (sitter->watches,
00740 add_function,
00741 remove_function,
00742 toggled_function,
00743 data,
00744 free_data_function);
00745 }
00746
00747 static dbus_bool_t
00748 handle_watch (DBusWatch *watch,
00749 unsigned int condition,
00750 void *data)
00751 {
00752 DBusBabysitter *sitter = data;
00753 int revents;
00754 int fd;
00755
00756 revents = 0;
00757 if (condition & DBUS_WATCH_READABLE)
00758 revents |= _DBUS_POLLIN;
00759 if (condition & DBUS_WATCH_ERROR)
00760 revents |= _DBUS_POLLERR;
00761 if (condition & DBUS_WATCH_HANGUP)
00762 revents |= _DBUS_POLLHUP;
00763
00764 fd = dbus_watch_get_socket (watch);
00765
00766 if (fd == sitter->error_pipe_from_child)
00767 handle_error_pipe (sitter, revents);
00768 else if (fd == sitter->socket_to_babysitter)
00769 handle_babysitter_socket (sitter, revents);
00770
00771 while (LIVE_CHILDREN (sitter) &&
00772 babysitter_iteration (sitter, FALSE))
00773 ;
00774
00775 return TRUE;
00776 }
00777
00779 #define READ_END 0
00780
00781 #define WRITE_END 1
00782
00783
00784
00785
00786
00787
00788 static int
00789 close_and_invalidate (int *fd)
00790 {
00791 int ret;
00792
00793 if (*fd < 0)
00794 return -1;
00795 else
00796 {
00797 ret = _dbus_close_socket (*fd, NULL);
00798 *fd = -1;
00799 }
00800
00801 return ret;
00802 }
00803
00804 static dbus_bool_t
00805 make_pipe (int p[2],
00806 DBusError *error)
00807 {
00808 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00809
00810 if (pipe (p) < 0)
00811 {
00812 dbus_set_error (error,
00813 DBUS_ERROR_SPAWN_FAILED,
00814 "Failed to create pipe for communicating with child process (%s)",
00815 _dbus_strerror (errno));
00816 return FALSE;
00817 }
00818
00819 return TRUE;
00820 }
00821
00822 static void
00823 do_write (int fd, const void *buf, size_t count)
00824 {
00825 size_t bytes_written;
00826 int ret;
00827
00828 bytes_written = 0;
00829
00830 again:
00831
00832 ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
00833
00834 if (ret < 0)
00835 {
00836 if (errno == EINTR)
00837 goto again;
00838 else
00839 {
00840 _dbus_warn ("Failed to write data to pipe!\n");
00841 exit (1);
00842 }
00843 }
00844 else
00845 bytes_written += ret;
00846
00847 if (bytes_written < count)
00848 goto again;
00849 }
00850
00851 static void
00852 write_err_and_exit (int fd, int msg)
00853 {
00854 int en = errno;
00855
00856 do_write (fd, &msg, sizeof (msg));
00857 do_write (fd, &en, sizeof (en));
00858
00859 exit (1);
00860 }
00861
00862 static void
00863 write_pid (int fd, pid_t pid)
00864 {
00865 int msg = CHILD_PID;
00866
00867 do_write (fd, &msg, sizeof (msg));
00868 do_write (fd, &pid, sizeof (pid));
00869 }
00870
00871 static void
00872 write_status_and_exit (int fd, int status)
00873 {
00874 int msg = CHILD_EXITED;
00875
00876 do_write (fd, &msg, sizeof (msg));
00877 do_write (fd, &status, sizeof (status));
00878
00879 exit (0);
00880 }
00881
00882 static void
00883 do_exec (int child_err_report_fd,
00884 char **argv,
00885 char **envp,
00886 DBusSpawnChildSetupFunc child_setup,
00887 void *user_data)
00888 {
00889 #ifdef DBUS_BUILD_TESTS
00890 int i, max_open;
00891 #endif
00892
00893 _dbus_verbose_reset ();
00894 _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
00895 _dbus_getpid ());
00896
00897 if (child_setup)
00898 (* child_setup) (user_data);
00899
00900 #ifdef DBUS_BUILD_TESTS
00901 max_open = sysconf (_SC_OPEN_MAX);
00902
00903 for (i = 3; i < max_open; i++)
00904 {
00905 int retval;
00906
00907 if (i == child_err_report_fd)
00908 continue;
00909
00910 retval = fcntl (i, F_GETFD);
00911
00912 if (retval != -1 && !(retval & FD_CLOEXEC))
00913 _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
00914 }
00915 #endif
00916
00917 if (envp == NULL)
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