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 #ifdef HAVE_SYSTEMD
00042 #ifdef HAVE_SYSLOG_H
00043 #include <syslog.h>
00044 #endif
00045 #include <systemd/sd-journal.h>
00046 #endif
00047
00048 extern char **environ;
00049
00055
00056
00057
00058
00059
00063 typedef enum
00064 {
00065 READ_STATUS_OK,
00066 READ_STATUS_ERROR,
00067 READ_STATUS_EOF
00068 } ReadStatus;
00069
00070 static ReadStatus
00071 read_ints (int fd,
00072 int *buf,
00073 int n_ints_in_buf,
00074 int *n_ints_read,
00075 DBusError *error)
00076 {
00077 size_t bytes = 0;
00078 ReadStatus retval;
00079
00080 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00081
00082 retval = READ_STATUS_OK;
00083
00084 while (TRUE)
00085 {
00086 ssize_t chunk;
00087 size_t to_read;
00088
00089 to_read = sizeof (int) * n_ints_in_buf - bytes;
00090
00091 if (to_read == 0)
00092 break;
00093
00094 again:
00095
00096 chunk = read (fd,
00097 ((char*)buf) + bytes,
00098 to_read);
00099
00100 if (chunk < 0 && errno == EINTR)
00101 goto again;
00102
00103 if (chunk < 0)
00104 {
00105 dbus_set_error (error,
00106 DBUS_ERROR_SPAWN_FAILED,
00107 "Failed to read from child pipe (%s)",
00108 _dbus_strerror (errno));
00109
00110 retval = READ_STATUS_ERROR;
00111 break;
00112 }
00113 else if (chunk == 0)
00114 {
00115 retval = READ_STATUS_EOF;
00116 break;
00117 }
00118 else
00119 bytes += chunk;
00120 }
00121
00122 *n_ints_read = (int)(bytes / sizeof(int));
00123
00124 return retval;
00125 }
00126
00127 static ReadStatus
00128 read_pid (int fd,
00129 pid_t *buf,
00130 DBusError *error)
00131 {
00132 size_t bytes = 0;
00133 ReadStatus retval;
00134
00135 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00136
00137 retval = READ_STATUS_OK;
00138
00139 while (TRUE)
00140 {
00141 ssize_t chunk;
00142 size_t to_read;
00143
00144 to_read = sizeof (pid_t) - bytes;
00145
00146 if (to_read == 0)
00147 break;
00148
00149 again:
00150
00151 chunk = read (fd,
00152 ((char*)buf) + bytes,
00153 to_read);
00154 if (chunk < 0 && errno == EINTR)
00155 goto again;
00156
00157 if (chunk < 0)
00158 {
00159 dbus_set_error (error,
00160 DBUS_ERROR_SPAWN_FAILED,
00161 "Failed to read from child pipe (%s)",
00162 _dbus_strerror (errno));
00163
00164 retval = READ_STATUS_ERROR;
00165 break;
00166 }
00167 else if (chunk == 0)
00168 {
00169 retval = READ_STATUS_EOF;
00170 break;
00171 }
00172 else
00173 bytes += chunk;
00174 }
00175
00176 return retval;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 enum
00229 {
00230 CHILD_EXITED,
00231 CHILD_FORK_FAILED,
00232 CHILD_EXEC_FAILED,
00233 CHILD_PID
00234 };
00235
00239 struct DBusBabysitter
00240 {
00241 int refcount;
00243 char *log_name;
00246 DBusSocket socket_to_babysitter;
00247 int error_pipe_from_child;
00249 pid_t sitter_pid;
00250 pid_t grandchild_pid;
00252 DBusWatchList *watches;
00254 DBusWatch *error_watch;
00255 DBusWatch *sitter_watch;
00257 DBusBabysitterFinishedFunc finished_cb;
00258 void *finished_data;
00259
00260 int errnum;
00261 int status;
00262 unsigned int have_child_status : 1;
00263 unsigned int have_fork_errnum : 1;
00264 unsigned int have_exec_errnum : 1;
00265 };
00266
00267 static DBusBabysitter*
00268 _dbus_babysitter_new (void)
00269 {
00270 DBusBabysitter *sitter;
00271
00272 sitter = dbus_new0 (DBusBabysitter, 1);
00273 if (sitter == NULL)
00274 return NULL;
00275
00276 sitter->refcount = 1;
00277
00278 sitter->socket_to_babysitter.fd = -1;
00279 sitter->error_pipe_from_child = -1;
00280
00281 sitter->sitter_pid = -1;
00282 sitter->grandchild_pid = -1;
00283
00284 sitter->watches = _dbus_watch_list_new ();
00285 if (sitter->watches == NULL)
00286 goto failed;
00287
00288 return sitter;
00289
00290 failed:
00291 _dbus_babysitter_unref (sitter);
00292 return NULL;
00293 }
00294
00301 DBusBabysitter *
00302 _dbus_babysitter_ref (DBusBabysitter *sitter)
00303 {
00304 _dbus_assert (sitter != NULL);
00305 _dbus_assert (sitter->refcount > 0);
00306
00307 sitter->refcount += 1;
00308
00309 return sitter;
00310 }
00311
00312 static void close_socket_to_babysitter (DBusBabysitter *sitter);
00313 static void close_error_pipe_from_child (DBusBabysitter *sitter);
00314
00323 void
00324 _dbus_babysitter_unref (DBusBabysitter *sitter)
00325 {
00326 _dbus_assert (sitter != NULL);
00327 _dbus_assert (sitter->refcount > 0);
00328
00329 sitter->refcount -= 1;
00330 if (sitter->refcount == 0)
00331 {
00332
00333
00334
00335
00336
00337
00338
00339 close_socket_to_babysitter (sitter);
00340
00341 close_error_pipe_from_child (sitter);
00342
00343 if (sitter->sitter_pid > 0)
00344 {
00345 int status;
00346 int ret;
00347
00348
00349
00350
00351
00352 ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
00353
00354
00355
00356
00357 if (ret == 0)
00358 kill (sitter->sitter_pid, SIGKILL);
00359
00360 if (ret == 0)
00361 {
00362 do
00363 {
00364 ret = waitpid (sitter->sitter_pid, &status, 0);
00365 }
00366 while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
00367 }
00368
00369 if (ret < 0)
00370 {
00371 if (errno == ECHILD)
00372 _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
00373 else
00374 _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
00375 errno, _dbus_strerror (errno));
00376 }
00377 else
00378 {
00379 _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
00380 (long) ret, (long) sitter->sitter_pid);
00381
00382 if (WIFEXITED (sitter->status))
00383 _dbus_verbose ("Babysitter exited with status %d\n",
00384 WEXITSTATUS (sitter->status));
00385 else if (WIFSIGNALED (sitter->status))
00386 _dbus_verbose ("Babysitter received signal %d\n",
00387 WTERMSIG (sitter->status));
00388 else
00389 _dbus_verbose ("Babysitter exited abnormally\n");
00390 }
00391
00392 sitter->sitter_pid = -1;
00393 }
00394
00395 if (sitter->watches)
00396 _dbus_watch_list_free (sitter->watches);
00397
00398 dbus_free (sitter->log_name);
00399
00400 dbus_free (sitter);
00401 }
00402 }
00403
00404 static ReadStatus
00405 read_data (DBusBabysitter *sitter,
00406 int fd)
00407 {
00408 int what;
00409 int got;
00410 DBusError error = DBUS_ERROR_INIT;
00411 ReadStatus r;
00412
00413 r = read_ints (fd, &what, 1, &got, &error);
00414
00415 switch (r)
00416 {
00417 case READ_STATUS_ERROR:
00418 _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
00419 dbus_error_free (&error);
00420 return r;
00421
00422 case READ_STATUS_EOF:
00423 return r;
00424
00425 case READ_STATUS_OK:
00426 break;
00427 }
00428
00429 if (got == 1)
00430 {
00431 switch (what)
00432 {
00433 case CHILD_EXITED:
00434 case CHILD_FORK_FAILED:
00435 case CHILD_EXEC_FAILED:
00436 {
00437 int arg;
00438
00439 r = read_ints (fd, &arg, 1, &got, &error);
00440
00441 switch (r)
00442 {
00443 case READ_STATUS_ERROR:
00444 _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
00445 dbus_error_free (&error);
00446 return r;
00447 case READ_STATUS_EOF:
00448 return r;
00449 case READ_STATUS_OK:
00450 break;
00451 }
00452
00453 if (got == 1)
00454 {
00455 if (what == CHILD_EXITED)
00456 {
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 sitter->have_child_status = TRUE;
00475 sitter->status = arg;
00476 _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
00477 WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
00478 WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
00479 }
00480 else if (what == CHILD_FORK_FAILED)
00481 {
00482 sitter->have_fork_errnum = TRUE;
00483 sitter->errnum = arg;
00484 _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
00485 }
00486 else if (what == CHILD_EXEC_FAILED)
00487 {
00488 sitter->have_exec_errnum = TRUE;
00489 sitter->errnum = arg;
00490 _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
00491 }
00492 }
00493 }
00494 break;
00495 case CHILD_PID:
00496 {
00497 pid_t pid = -1;
00498
00499 r = read_pid (fd, &pid, &error);
00500
00501 switch (r)
00502 {
00503 case READ_STATUS_ERROR:
00504 _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
00505 dbus_error_free (&error);
00506 return r;
00507 case READ_STATUS_EOF:
00508 return r;
00509 case READ_STATUS_OK:
00510 break;
00511 }
00512
00513 sitter->grandchild_pid = pid;
00514
00515 _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
00516 }
00517 break;
00518 default:
00519 _dbus_warn ("Unknown message received from babysitter process\n");
00520 break;
00521 }
00522 }
00523
00524 return r;
00525 }
00526
00527 static void
00528 close_socket_to_babysitter (DBusBabysitter *sitter)
00529 {
00530 _dbus_verbose ("Closing babysitter\n");
00531
00532 if (sitter->sitter_watch != NULL)
00533 {
00534 _dbus_assert (sitter->watches != NULL);
00535 _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
00536 _dbus_watch_invalidate (sitter->sitter_watch);
00537 _dbus_watch_unref (sitter->sitter_watch);
00538 sitter->sitter_watch = NULL;
00539 }
00540
00541 if (sitter->socket_to_babysitter.fd >= 0)
00542 {
00543 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
00544 sitter->socket_to_babysitter.fd = -1;
00545 }
00546 }
00547
00548 static void
00549 close_error_pipe_from_child (DBusBabysitter *sitter)
00550 {
00551 _dbus_verbose ("Closing child error\n");
00552
00553 if (sitter->error_watch != NULL)
00554 {
00555 _dbus_assert (sitter->watches != NULL);
00556 _dbus_watch_list_remove_watch (sitter->watches, sitter->error_watch);
00557 _dbus_watch_invalidate (sitter->error_watch);
00558 _dbus_watch_unref (sitter->error_watch);
00559 sitter->error_watch = NULL;
00560 }
00561
00562 if (sitter->error_pipe_from_child >= 0)
00563 {
00564 _dbus_close (sitter->error_pipe_from_child, NULL);
00565 sitter->error_pipe_from_child = -1;
00566 }
00567 }
00568
00569 static void
00570 handle_babysitter_socket (DBusBabysitter *sitter,
00571 int revents)
00572 {
00573
00574
00575
00576
00577 if (revents & _DBUS_POLLIN)
00578 {
00579 _dbus_verbose ("Reading data from babysitter\n");
00580 if (read_data (sitter, sitter->socket_to_babysitter.fd) != READ_STATUS_OK)
00581 close_socket_to_babysitter (sitter);
00582 }
00583 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00584 {
00585 close_socket_to_babysitter (sitter);
00586 }
00587 }
00588
00589 static void
00590 handle_error_pipe (DBusBabysitter *sitter,
00591 int revents)
00592 {
00593 if (revents & _DBUS_POLLIN)
00594 {
00595 _dbus_verbose ("Reading data from child error\n");
00596 if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
00597 close_error_pipe_from_child (sitter);
00598 }
00599 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00600 {
00601 close_error_pipe_from_child (sitter);
00602 }
00603 }
00604
00605
00606 static dbus_bool_t
00607 babysitter_iteration (DBusBabysitter *sitter,
00608 dbus_bool_t block)
00609 {
00610 DBusPollFD fds[2];
00611 int i;
00612 dbus_bool_t descriptors_ready;
00613
00614 descriptors_ready = FALSE;
00615
00616 i = 0;
00617
00618 if (sitter->error_pipe_from_child >= 0)
00619 {
00620 fds[i].fd = sitter->error_pipe_from_child;
00621 fds[i].events = _DBUS_POLLIN;
00622 fds[i].revents = 0;
00623 ++i;
00624 }
00625
00626 if (sitter->socket_to_babysitter.fd >= 0)
00627 {
00628 fds[i].fd = sitter->socket_to_babysitter.fd;
00629 fds[i].events = _DBUS_POLLIN;
00630 fds[i].revents = 0;
00631 ++i;
00632 }
00633
00634 if (i > 0)
00635 {
00636 int ret;
00637
00638 do
00639 {
00640 ret = _dbus_poll (fds, i, 0);
00641 }
00642 while (ret < 0 && errno == EINTR);
00643
00644 if (ret == 0 && block)
00645 {
00646 do
00647 {
00648 ret = _dbus_poll (fds, i, -1);
00649 }
00650 while (ret < 0 && errno == EINTR);
00651 }
00652
00653 if (ret > 0)
00654 {
00655 descriptors_ready = TRUE;
00656
00657 while (i > 0)
00658 {
00659 --i;
00660 if (fds[i].fd == sitter->error_pipe_from_child)
00661 handle_error_pipe (sitter, fds[i].revents);
00662 else if (fds[i].fd == sitter->socket_to_babysitter.fd)
00663 handle_babysitter_socket (sitter, fds[i].revents);
00664 }
00665 }
00666 }
00667
00668 return descriptors_ready;
00669 }
00670
00675 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter.fd >= 0 || (sitter)->error_pipe_from_child >= 0)
00676
00683 void
00684 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
00685 {
00686
00687 while (LIVE_CHILDREN (sitter) &&
00688 sitter->grandchild_pid == -1)
00689 babysitter_iteration (sitter, TRUE);
00690
00691 _dbus_verbose ("Got child PID %ld for killing\n",
00692 (long) sitter->grandchild_pid);
00693
00694 if (sitter->grandchild_pid == -1)
00695 return;
00696
00697 kill (sitter->grandchild_pid, SIGKILL);
00698 }
00699
00705 dbus_bool_t
00706 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
00707 {
00708
00709
00710 while (LIVE_CHILDREN (sitter) &&
00711 babysitter_iteration (sitter, FALSE))
00712 ;
00713
00714
00715 return sitter->socket_to_babysitter.fd < 0;
00716 }
00717
00730 dbus_bool_t
00731 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
00732 int *status)
00733 {
00734 if (!_dbus_babysitter_get_child_exited (sitter))
00735 _dbus_assert_not_reached ("Child has not exited");
00736
00737 if (!sitter->have_child_status ||
00738 !(WIFEXITED (sitter->status)))
00739 return FALSE;
00740
00741 *status = WEXITSTATUS (sitter->status);
00742 return TRUE;
00743 }
00744
00754 void
00755 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
00756 DBusError *error)
00757 {
00758 if (!_dbus_babysitter_get_child_exited (sitter))
00759 return;
00760
00761
00762
00763
00764
00765 if (sitter->have_exec_errnum)
00766 {
00767 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
00768 "Failed to execute program %s: %s",
00769 sitter->log_name, _dbus_strerror (sitter->errnum));
00770 }
00771 else if (sitter->have_fork_errnum)
00772 {
00773 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00774 "Failed to fork a new process %s: %s",
00775 sitter->log_name, _dbus_strerror (sitter->errnum));
00776 }
00777 else if (sitter->have_child_status)
00778 {
00779 if (WIFEXITED (sitter->status))
00780 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
00781 "Process %s exited with status %d",
00782 sitter->log_name, WEXITSTATUS (sitter->status));
00783 else if (WIFSIGNALED (sitter->status))
00784 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
00785 "Process %s received signal %d",
00786 sitter->log_name, WTERMSIG (sitter->status));
00787 else
00788 dbus_set_error (error, DBUS_ERROR_FAILED,
00789 "Process %s exited abnormally",
00790 sitter->log_name);
00791 }
00792 else
00793 {
00794 dbus_set_error (error, DBUS_ERROR_FAILED,
00795 "Process %s exited, reason unknown",
00796 sitter->log_name);
00797 }
00798 }
00799
00812 dbus_bool_t
00813 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
00814 DBusAddWatchFunction add_function,
00815 DBusRemoveWatchFunction remove_function,
00816 DBusWatchToggledFunction toggled_function,
00817 void *data,
00818 DBusFreeFunction free_data_function)
00819 {
00820 return _dbus_watch_list_set_functions (sitter->watches,
00821 add_function,
00822 remove_function,
00823 toggled_function,
00824 data,
00825 free_data_function);
00826 }
00827
00828 static dbus_bool_t
00829 handle_watch (DBusWatch *watch,
00830 unsigned int condition,
00831 void *data)
00832 {
00833 DBusBabysitter *sitter = _dbus_babysitter_ref (data);
00834 int revents;
00835 int fd;
00836
00837 revents = 0;
00838 if (condition & DBUS_WATCH_READABLE)
00839 revents |= _DBUS_POLLIN;
00840 if (condition & DBUS_WATCH_ERROR)
00841 revents |= _DBUS_POLLERR;
00842 if (condition & DBUS_WATCH_HANGUP)
00843 revents |= _DBUS_POLLHUP;
00844
00845 fd = dbus_watch_get_socket (watch);
00846
00847 if (fd == sitter->error_pipe_from_child)
00848 handle_error_pipe (sitter, revents);
00849 else if (fd == sitter->socket_to_babysitter.fd)
00850 handle_babysitter_socket (sitter, revents);
00851
00852 while (LIVE_CHILDREN (sitter) &&
00853 babysitter_iteration (sitter, FALSE))
00854 ;
00855
00856
00857
00858 _dbus_assert (sitter->socket_to_babysitter.fd != -1 || sitter->sitter_watch == NULL);
00859 _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
00860
00861 if (_dbus_babysitter_get_child_exited (sitter) &&
00862 sitter->finished_cb != NULL)
00863 {
00864 sitter->finished_cb (sitter, sitter->finished_data);
00865 sitter->finished_cb = NULL;
00866 }
00867
00868 _dbus_babysitter_unref (sitter);
00869 return TRUE;
00870 }
00871
00873 #define READ_END 0
00874
00875 #define WRITE_END 1
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 static int
00888 close_and_invalidate (int *fd)
00889 {
00890 int ret;
00891
00892 if (*fd < 0)
00893 return -1;
00894 else
00895 {
00896 ret = _dbus_close (*fd, NULL);
00897 *fd = -1;
00898 }
00899
00900 return ret;
00901 }
00902
00903 static dbus_bool_t
00904 make_pipe (int p[2],
00905 DBusError *error)
00906 {
00907 int retval;
00908
00909 #ifdef HAVE_PIPE2
00910 dbus_bool_t cloexec_done;
00911
00912 retval = pipe2 (p, O_CLOEXEC);
00913 cloexec_done = retval >= 0;
00914
00915
00916
00917 if (retval < 0 && errno == ENOSYS)
00918 #endif
00919 {
00920 retval = pipe(p);
00921 }
00922
00923 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00924
00925 if (retval < 0)
00926 {
00927 dbus_set_error (error,
00928 DBUS_ERROR_SPAWN_FAILED,
00929 "Failed to create pipe for communicating with child process (%s)",
00930 _dbus_strerror (errno));
00931 return FALSE;
00932 }
00933
00934 #ifdef HAVE_PIPE2
00935 if (!cloexec_done)
00936 #endif
00937 {
00938 _dbus_fd_set_close_on_exec (p[0]);
00939 _dbus_fd_set_close_on_exec (p[1]);
00940 }
00941
00942 return TRUE;
00943 }
00944
00945 static void
00946 do_write (int fd, const void *buf, size_t count)
00947 {
00948 size_t bytes_written;
00949 int ret;
00950
00951 bytes_written = 0;
00952
00953 again:
00954
00955 ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
00956
00957 if (ret < 0)
00958 {
00959 if (errno == EINTR)
00960 goto again;
00961 else
00962 {
00963 _dbus_warn ("Failed to write data to pipe!\n");
00964 exit (1);
00965 }
00966 }
00967 else
00968 bytes_written += ret;
00969
00970 if (bytes_written < count)
00971 goto again;
00972 }
00973
00974 static void
00975 write_err_and_exit (int fd, int msg)
00976 {
00977 int en = errno;
00978
00979 do_write (fd, &msg, sizeof (msg));
00980 do_write (fd, &en, sizeof (en));
00981
00982 exit (1);
00983 }
00984
00985 static void
00986 write_pid (int fd, pid_t pid)
00987 {
00988 int msg = CHILD_PID;
00989
00990 do_write (fd, &msg, sizeof (msg));
00991 do_write (fd, &pid, sizeof (pid));
00992 }
00993
00994 static void
00995 write_status_and_exit (int fd, int status)
00996 {
00997 int msg = CHILD_EXITED;
00998
00999 do_write (fd, &msg, sizeof (msg));
01000 do_write (fd, &status, sizeof (status));
01001
01002 exit (0);
01003 }
01004
01005 static void
01006 do_exec (int child_err_report_fd,
01007 char **argv,
01008 char **envp,
01009 DBusSpawnChildSetupFunc child_setup,
01010 void *user_data)
01011 {
01012 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01013 int i, max_open;
01014 #endif
01015
01016 _dbus_verbose_reset ();
01017 _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
01018 _dbus_getpid ());
01019
01020 if (child_setup)
01021 (* child_setup) (user_data);
01022
01023 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01024 max_open = sysconf (_SC_OPEN_MAX);
01025
01026 for (i = 3; i < max_open; i++)
01027 {
01028 int retval;
01029
01030 if (i == child_err_report_fd)
01031 continue;
01032
01033 retval = fcntl (i, F_GETFD);
01034
01035 if (retval != -1 && !(retval & FD_CLOEXEC))
01036 _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
01037 }
01038 #endif
01039
01040 if (envp == NULL)
01041 {
01042 _dbus_assert (environ != NULL);
01043
01044 envp = environ;
01045 }
01046
01047 execve (argv[0], argv, envp);
01048
01049
01050 write_err_and_exit (child_err_report_fd,
01051 CHILD_EXEC_FAILED);
01052 }
01053
01054 static void
01055 check_babysit_events (pid_t grandchild_pid,
01056 int parent_pipe,
01057 int revents)
01058 {
01059 pid_t ret;
01060 int status;
01061
01062 do
01063 {
01064 ret = waitpid (grandchild_pid, &status, WNOHANG);
01065
01066
01067
01068 }
01069 while (ret < 0 && errno == EINTR);
01070
01071 if (ret == 0)
01072 {
01073 _dbus_verbose ("no child exited\n");
01074
01075 ;
01076 }
01077 else if (ret < 0)
01078 {
01079
01080 _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
01081 _dbus_strerror (errno));
01082 exit (1);
01083 }
01084 else if (ret == grandchild_pid)
01085 {
01086
01087 _dbus_verbose ("reaped child pid %ld\n", (long) ret);
01088
01089 write_status_and_exit (parent_pipe, status);
01090 }
01091 else
01092 {
01093 _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
01094 (int) ret);
01095 exit (1);
01096 }
01097
01098 if (revents & _DBUS_POLLIN)
01099 {
01100 _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
01101 }
01102
01103 if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
01104 {
01105
01106 _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
01107 exit (0);
01108 }
01109 }
01110
01111 static int babysit_sigchld_pipe = -1;
01112
01113 static void
01114 babysit_signal_handler (int signo)
01115 {
01116 char b = '\0';
01117 again:
01118 if (write (babysit_sigchld_pipe, &b, 1) <= 0)
01119 if (errno == EINTR)
01120 goto again;
01121 }
01122
01123 static void
01124 babysit (pid_t grandchild_pid,
01125 int parent_pipe)
01126 {
01127 int sigchld_pipe[2];
01128
01129
01130
01131
01132 _dbus_verbose_reset ();
01133
01134
01135
01136
01137
01138
01139 if (pipe (sigchld_pipe) < 0)
01140 {
01141 _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
01142 exit (1);
01143 }
01144
01145 babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
01146
01147 _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
01148
01149 write_pid (parent_pipe, grandchild_pid);
01150
01151 check_babysit_events (grandchild_pid, parent_pipe, 0);
01152
01153 while (TRUE)
01154 {
01155 DBusPollFD pfds[2];
01156
01157 pfds[0].fd = parent_pipe;
01158 pfds[0].events = _DBUS_POLLIN;
01159 pfds[0].revents = 0;
01160
01161 pfds[1].fd = sigchld_pipe[READ_END];
01162 pfds[1].events = _DBUS_POLLIN;
01163 pfds[1].revents = 0;
01164
01165 if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
01166 {
01167 _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
01168 exit (1);
01169 }
01170
01171 if (pfds[0].revents != 0)
01172 {
01173 check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
01174 }
01175 else if (pfds[1].revents & _DBUS_POLLIN)
01176 {
01177 char b;
01178 if (read (sigchld_pipe[READ_END], &b, 1) == -1)
01179 {
01180
01181 }
01182
01183 check_babysit_events (grandchild_pid, parent_pipe, 0);
01184 }
01185 }
01186
01187 exit (1);
01188 }
01189
01209 dbus_bool_t
01210 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
01211 const char *log_name,
01212 char **argv,
01213 char **env,
01214 DBusSpawnChildSetupFunc child_setup,
01215 void *user_data,
01216 DBusError *error)
01217 {
01218 DBusBabysitter *sitter;
01219 int child_err_report_pipe[2] = { -1, -1 };
01220 DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT };
01221 pid_t pid;
01222 #ifdef HAVE_SYSTEMD
01223 int fd_out = -1;
01224 int fd_err = -1;
01225 #endif
01226
01227 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01228 _dbus_assert (argv[0] != NULL);
01229
01230 if (sitter_p != NULL)
01231 *sitter_p = NULL;
01232
01233 sitter = NULL;
01234
01235 sitter = _dbus_babysitter_new ();
01236 if (sitter == NULL)
01237 {
01238 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01239 return FALSE;
01240 }
01241
01242 sitter->log_name = _dbus_strdup (log_name);
01243 if (sitter->log_name == NULL && log_name != NULL)
01244 {
01245 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01246 goto cleanup_and_fail;
01247 }
01248
01249 if (sitter->log_name == NULL)
01250 sitter->log_name = _dbus_strdup (argv[0]);
01251
01252 if (sitter->log_name == NULL)
01253 {
01254 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01255 goto cleanup_and_fail;
01256 }
01257
01258 if (!make_pipe (child_err_report_pipe, error))
01259 goto cleanup_and_fail;
01260
01261 if (!_dbus_socketpair (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
01262 goto cleanup_and_fail;
01263
01264
01265
01266
01267
01268
01269 sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
01270 DBUS_WATCH_READABLE,
01271 TRUE, handle_watch, sitter, NULL);
01272 if (sitter->error_watch == NULL)
01273 {
01274 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01275 goto cleanup_and_fail;
01276 }
01277
01278 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch))
01279 {
01280
01281
01282 _dbus_watch_invalidate (sitter->error_watch);
01283 _dbus_watch_unref (sitter->error_watch);
01284 sitter->error_watch = NULL;
01285
01286 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01287 goto cleanup_and_fail;
01288 }
01289
01290 sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0].fd,
01291 DBUS_WATCH_READABLE,
01292 TRUE, handle_watch, sitter, NULL);
01293 if (sitter->sitter_watch == NULL)
01294 {
01295 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01296 goto cleanup_and_fail;
01297 }
01298
01299 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
01300 {
01301
01302
01303 _dbus_watch_invalidate (sitter->sitter_watch);
01304 _dbus_watch_unref (sitter->sitter_watch);
01305 sitter->sitter_watch = NULL;
01306
01307 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01308 goto cleanup_and_fail;
01309 }
01310
01311 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01312
01313 #ifdef HAVE_SYSTEMD
01314
01315
01316
01317
01318 fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
01319 fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
01320 #endif
01321
01322 pid = fork ();
01323
01324 if (pid < 0)
01325 {
01326 dbus_set_error (error,
01327 DBUS_ERROR_SPAWN_FORK_FAILED,
01328 "Failed to fork (%s)",
01329 _dbus_strerror (errno));
01330 goto cleanup_and_fail;
01331 }
01332 else if (pid == 0)
01333 {
01334
01335 int grandchild_pid;
01336
01337
01338
01339
01340 signal (SIGPIPE, SIG_DFL);
01341
01342
01343 close_and_invalidate (&child_err_report_pipe[READ_END]);
01344 close_and_invalidate (&babysitter_pipe[0].fd);
01345
01346
01347 grandchild_pid = fork ();
01348
01349 if (grandchild_pid < 0)
01350 {
01351 write_err_and_exit (babysitter_pipe[1].fd,
01352 CHILD_FORK_FAILED);
01353 _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
01354 }
01355 else if (grandchild_pid == 0)
01356 {
01357 #ifdef __linux__
01358 int fd = -1;
01359
01360 #ifdef O_CLOEXEC
01361 fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
01362 #endif
01363
01364 if (fd < 0)
01365 {
01366 fd = open ("/proc/self/oom_score_adj", O_WRONLY);
01367 _dbus_fd_set_close_on_exec (fd);
01368 }
01369
01370 if (fd >= 0)
01371 {
01372 if (write (fd, "0", sizeof (char)) < 0)
01373 _dbus_warn ("writing oom_score_adj error: %s\n", strerror (errno));
01374 _dbus_close (fd, NULL);
01375 }
01376 #endif
01377
01378
01379 signal (SIGPIPE, SIG_IGN);
01380
01381 close_and_invalidate (&babysitter_pipe[1].fd);
01382 #ifdef HAVE_SYSTEMD
01383
01384 if (fd_out >= 0)
01385 dup2 (fd_out, STDOUT_FILENO);
01386 if (fd_err >= 0)
01387 dup2 (fd_err, STDERR_FILENO);
01388 close_and_invalidate (&fd_out);
01389 close_and_invalidate (&fd_err);
01390 #endif
01391 do_exec (child_err_report_pipe[WRITE_END],
01392 argv,
01393 env,
01394 child_setup, user_data);
01395 _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
01396 }
01397 else
01398 {
01399 close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01400 #ifdef HAVE_SYSTEMD
01401 close_and_invalidate (&fd_out);
01402 close_and_invalidate (&fd_err);
01403 #endif
01404 babysit (grandchild_pid, babysitter_pipe[1].fd);
01405 _dbus_assert_not_reached ("Got to code after babysit()");
01406 }
01407 }
01408 else
01409 {
01410
01411 close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01412 close_and_invalidate (&babysitter_pipe[1].fd);
01413 #ifdef HAVE_SYSTEMD
01414 close_and_invalidate (&fd_out);
01415 close_and_invalidate (&fd_err);
01416 #endif
01417
01418 sitter->socket_to_babysitter = babysitter_pipe[0];
01419 babysitter_pipe[0].fd = -1;
01420
01421 sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
01422 child_err_report_pipe[READ_END] = -1;
01423
01424 sitter->sitter_pid = pid;
01425
01426 if (sitter_p != NULL)
01427 *sitter_p = sitter;
01428 else
01429 _dbus_babysitter_unref (sitter);
01430
01431 dbus_free_string_array (env);
01432
01433 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01434
01435 return TRUE;
01436 }
01437
01438 cleanup_and_fail:
01439
01440 _DBUS_ASSERT_ERROR_IS_SET (error);
01441
01442 close_and_invalidate (&child_err_report_pipe[READ_END]);
01443 close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01444 close_and_invalidate (&babysitter_pipe[0].fd);
01445 close_and_invalidate (&babysitter_pipe[1].fd);
01446 #ifdef HAVE_SYSTEMD
01447 close_and_invalidate (&fd_out);
01448 close_and_invalidate (&fd_err);
01449 #endif
01450
01451 if (sitter != NULL)
01452 _dbus_babysitter_unref (sitter);
01453
01454 return FALSE;
01455 }
01456
01457 void
01458 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
01459 DBusBabysitterFinishedFunc finished,
01460 void *user_data)
01461 {
01462 sitter->finished_cb = finished;
01463 sitter->finished_data = user_data;
01464 }
01465
01468 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01469
01470 static char *
01471 get_test_exec (const char *exe,
01472 DBusString *scratch_space)
01473 {
01474 const char *dbus_test_exec;
01475
01476 dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
01477
01478 if (dbus_test_exec == NULL)
01479 dbus_test_exec = DBUS_TEST_EXEC;
01480
01481 if (!_dbus_string_init (scratch_space))
01482 return NULL;
01483
01484 if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
01485 dbus_test_exec, exe, DBUS_EXEEXT))
01486 {
01487 _dbus_string_free (scratch_space);
01488 return NULL;
01489 }
01490
01491 return _dbus_string_get_data (scratch_space);
01492 }
01493
01494 static void
01495 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
01496 {
01497 while (LIVE_CHILDREN (sitter))
01498 babysitter_iteration (sitter, TRUE);
01499 }
01500
01501 static dbus_bool_t
01502 check_spawn_nonexistent (void *data)
01503 {
01504 char *argv[4] = { NULL, NULL, NULL, NULL };
01505 DBusBabysitter *sitter = NULL;
01506 DBusError error = DBUS_ERROR_INIT;
01507
01508
01509
01510 argv[0] = "/this/does/not/exist/32542sdgafgafdg";
01511 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv,
01512 NULL, NULL, NULL,
01513 &error))
01514 {
01515 _dbus_babysitter_block_for_child_exit (sitter);
01516 _dbus_babysitter_set_child_exit_error (sitter, &error);
01517 }
01518
01519 if (sitter)
01520 _dbus_babysitter_unref (sitter);
01521
01522 if (!dbus_error_is_set (&error))
01523 {
01524 _dbus_warn ("Did not get an error launching nonexistent executable\n");
01525 return FALSE;
01526 }
01527
01528 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01529 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
01530 {
01531 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
01532 error.name, error.message);
01533 dbus_error_free (&error);
01534 return FALSE;
01535 }
01536
01537 dbus_error_free (&error);
01538
01539 return TRUE;
01540 }
01541
01542 static dbus_bool_t
01543 check_spawn_segfault (void *data)
01544 {
01545 char *argv[4] = { NULL, NULL, NULL, NULL };
01546 DBusBabysitter *sitter = NULL;
01547 DBusError error = DBUS_ERROR_INIT;
01548 DBusString argv0;
01549
01550
01551
01552 argv[0] = get_test_exec ("test-segfault", &argv0);
01553
01554 if (argv[0] == NULL)
01555 {
01556
01557 return TRUE;
01558 }
01559
01560 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
01561 NULL, NULL, NULL,
01562 &error))
01563 {
01564 _dbus_babysitter_block_for_child_exit (sitter);
01565 _dbus_babysitter_set_child_exit_error (sitter, &error);
01566 }
01567
01568 _dbus_string_free (&argv0);
01569
01570 if (sitter)
01571 _dbus_babysitter_unref (sitter);
01572
01573 if (!dbus_error_is_set (&error))
01574 {
01575 _dbus_warn ("Did not get an error launching segfaulting binary\n");
01576 return FALSE;
01577 }
01578
01579 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01580 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01581 {
01582 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
01583 error.name, error.message);
01584 dbus_error_free (&error);
01585 return FALSE;
01586 }
01587
01588 dbus_error_free (&error);
01589
01590 return TRUE;
01591 }
01592
01593 static dbus_bool_t
01594 check_spawn_exit (void *data)
01595 {
01596 char *argv[4] = { NULL, NULL, NULL, NULL };
01597 DBusBabysitter *sitter = NULL;
01598 DBusError error = DBUS_ERROR_INIT;
01599 DBusString argv0;
01600
01601
01602
01603 argv[0] = get_test_exec ("test-exit", &argv0);
01604
01605 if (argv[0] == NULL)
01606 {
01607
01608 return TRUE;
01609 }
01610
01611 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
01612 NULL, NULL, NULL,
01613 &error))
01614 {
01615 _dbus_babysitter_block_for_child_exit (sitter);
01616 _dbus_babysitter_set_child_exit_error (sitter, &error);
01617 }
01618
01619 _dbus_string_free (&argv0);
01620
01621 if (sitter)
01622 _dbus_babysitter_unref (sitter);
01623
01624 if (!dbus_error_is_set (&error))
01625 {
01626 _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
01627 return FALSE;
01628 }
01629
01630 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01631 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
01632 {
01633 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
01634 error.name, error.message);
01635 dbus_error_free (&error);
01636 return FALSE;
01637 }
01638
01639 dbus_error_free (&error);
01640
01641 return TRUE;
01642 }
01643
01644 static dbus_bool_t
01645 check_spawn_and_kill (void *data)
01646 {
01647 char *argv[4] = { NULL, NULL, NULL, NULL };
01648 DBusBabysitter *sitter = NULL;
01649 DBusError error = DBUS_ERROR_INIT;
01650 DBusString argv0;
01651
01652
01653
01654 argv[0] = get_test_exec ("test-sleep-forever", &argv0);
01655
01656 if (argv[0] == NULL)
01657 {
01658
01659 return TRUE;
01660 }
01661
01662 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
01663 NULL, NULL, NULL,
01664 &error))
01665 {
01666 _dbus_babysitter_kill_child (sitter);
01667
01668 _dbus_babysitter_block_for_child_exit (sitter);
01669
01670 _dbus_babysitter_set_child_exit_error (sitter, &error);
01671 }
01672
01673 _dbus_string_free (&argv0);
01674
01675 if (sitter)
01676 _dbus_babysitter_unref (sitter);
01677
01678 if (!dbus_error_is_set (&error))
01679 {
01680 _dbus_warn ("Did not get an error after killing spawned binary\n");
01681 return FALSE;
01682 }
01683
01684 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01685 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01686 {
01687 _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
01688 error.name, error.message);
01689 dbus_error_free (&error);
01690 return FALSE;
01691 }
01692
01693 dbus_error_free (&error);
01694
01695 return TRUE;
01696 }
01697
01698 dbus_bool_t
01699 _dbus_spawn_test (const char *test_data_dir)
01700 {
01701 if (!_dbus_test_oom_handling ("spawn_nonexistent",
01702 check_spawn_nonexistent,
01703 NULL))
01704 return FALSE;
01705
01706 if (!_dbus_test_oom_handling ("spawn_segfault",
01707 check_spawn_segfault,
01708 NULL))
01709 return FALSE;
01710
01711 if (!_dbus_test_oom_handling ("spawn_exit",
01712 check_spawn_exit,
01713 NULL))
01714 return FALSE;
01715
01716 if (!_dbus_test_oom_handling ("spawn_and_kill",
01717 check_spawn_and_kill,
01718 NULL))
01719 return FALSE;
01720
01721 return TRUE;
01722 }
01723 #endif