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