D-Bus 1.6.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-spawn.c Wrapper around fork/exec 00003 * 00004 * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. 00005 * Copyright (C) 2003 CodeFactory AB 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 * I'm pretty sure this whole spawn file could be made simpler, 00051 * if you thought about it a bit. 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; /* EOF */ 00111 } 00112 else /* chunk > 0 */ 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; /* EOF */ 00165 } 00166 else /* chunk > 0 */ 00167 bytes += chunk; 00168 } 00169 00170 return retval; 00171 } 00172 00173 /* The implementation uses an intermediate child between the main process 00174 * and the grandchild. The grandchild is our spawned process. The intermediate 00175 * child is a babysitter process; it keeps track of when the grandchild 00176 * exits/crashes, and reaps the grandchild. 00177 */ 00178 00179 /* Messages from children to parents */ 00180 enum 00181 { 00182 CHILD_EXITED, /* This message is followed by the exit status int */ 00183 CHILD_FORK_FAILED, /* Followed by errno */ 00184 CHILD_EXEC_FAILED, /* Followed by errno */ 00185 CHILD_PID /* Followed by pid_t */ 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 DBusBabysitterFinishedFunc finished_cb; 00209 void *finished_data; 00210 00211 int errnum; 00212 int status; 00213 unsigned int have_child_status : 1; 00214 unsigned int have_fork_errnum : 1; 00215 unsigned int have_exec_errnum : 1; 00216 }; 00217 00218 static DBusBabysitter* 00219 _dbus_babysitter_new (void) 00220 { 00221 DBusBabysitter *sitter; 00222 00223 sitter = dbus_new0 (DBusBabysitter, 1); 00224 if (sitter == NULL) 00225 return NULL; 00226 00227 sitter->refcount = 1; 00228 00229 sitter->socket_to_babysitter = -1; 00230 sitter->error_pipe_from_child = -1; 00231 00232 sitter->sitter_pid = -1; 00233 sitter->grandchild_pid = -1; 00234 00235 sitter->watches = _dbus_watch_list_new (); 00236 if (sitter->watches == NULL) 00237 goto failed; 00238 00239 return sitter; 00240 00241 failed: 00242 _dbus_babysitter_unref (sitter); 00243 return NULL; 00244 } 00245 00252 DBusBabysitter * 00253 _dbus_babysitter_ref (DBusBabysitter *sitter) 00254 { 00255 _dbus_assert (sitter != NULL); 00256 _dbus_assert (sitter->refcount > 0); 00257 00258 sitter->refcount += 1; 00259 00260 return sitter; 00261 } 00262 00263 static void close_socket_to_babysitter (DBusBabysitter *sitter); 00264 static void close_error_pipe_from_child (DBusBabysitter *sitter); 00265 00274 void 00275 _dbus_babysitter_unref (DBusBabysitter *sitter) 00276 { 00277 _dbus_assert (sitter != NULL); 00278 _dbus_assert (sitter->refcount > 0); 00279 00280 sitter->refcount -= 1; 00281 if (sitter->refcount == 0) 00282 { 00283 /* If we haven't forked other babysitters 00284 * since this babysitter and socket were 00285 * created then this close will cause the 00286 * babysitter to wake up from poll with 00287 * a hangup and then the babysitter will 00288 * quit itself. 00289 */ 00290 close_socket_to_babysitter (sitter); 00291 00292 close_error_pipe_from_child (sitter); 00293 00294 if (sitter->sitter_pid > 0) 00295 { 00296 int status; 00297 int ret; 00298 00299 /* It's possible the babysitter died on its own above 00300 * from the close, or was killed randomly 00301 * by some other process, so first try to reap it 00302 */ 00303 ret = waitpid (sitter->sitter_pid, &status, WNOHANG); 00304 00305 /* If we couldn't reap the child then kill it, and 00306 * try again 00307 */ 00308 if (ret == 0) 00309 kill (sitter->sitter_pid, SIGKILL); 00310 00311 again: 00312 if (ret == 0) 00313 ret = waitpid (sitter->sitter_pid, &status, 0); 00314 00315 if (ret < 0) 00316 { 00317 if (errno == EINTR) 00318 goto again; 00319 else if (errno == ECHILD) 00320 _dbus_warn ("Babysitter process not available to be reaped; should not happen\n"); 00321 else 00322 _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n", 00323 errno, _dbus_strerror (errno)); 00324 } 00325 else 00326 { 00327 _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n", 00328 (long) ret, (long) sitter->sitter_pid); 00329 00330 if (WIFEXITED (sitter->status)) 00331 _dbus_verbose ("Babysitter exited with status %d\n", 00332 WEXITSTATUS (sitter->status)); 00333 else if (WIFSIGNALED (sitter->status)) 00334 _dbus_verbose ("Babysitter received signal %d\n", 00335 WTERMSIG (sitter->status)); 00336 else 00337 _dbus_verbose ("Babysitter exited abnormally\n"); 00338 } 00339 00340 sitter->sitter_pid = -1; 00341 } 00342 00343 if (sitter->watches) 00344 _dbus_watch_list_free (sitter->watches); 00345 00346 dbus_free (sitter->executable); 00347 00348 dbus_free (sitter); 00349 } 00350 } 00351 00352 static ReadStatus 00353 read_data (DBusBabysitter *sitter, 00354 int fd) 00355 { 00356 int what; 00357 int got; 00358 DBusError error = DBUS_ERROR_INIT; 00359 ReadStatus r; 00360 00361 r = read_ints (fd, &what, 1, &got, &error); 00362 00363 switch (r) 00364 { 00365 case READ_STATUS_ERROR: 00366 _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message); 00367 dbus_error_free (&error); 00368 return r; 00369 00370 case READ_STATUS_EOF: 00371 return r; 00372 00373 case READ_STATUS_OK: 00374 break; 00375 } 00376 00377 if (got == 1) 00378 { 00379 switch (what) 00380 { 00381 case CHILD_EXITED: 00382 case CHILD_FORK_FAILED: 00383 case CHILD_EXEC_FAILED: 00384 { 00385 int arg; 00386 00387 r = read_ints (fd, &arg, 1, &got, &error); 00388 00389 switch (r) 00390 { 00391 case READ_STATUS_ERROR: 00392 _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message); 00393 dbus_error_free (&error); 00394 return r; 00395 case READ_STATUS_EOF: 00396 return r; 00397 case READ_STATUS_OK: 00398 break; 00399 } 00400 00401 if (got == 1) 00402 { 00403 if (what == CHILD_EXITED) 00404 { 00405 sitter->have_child_status = TRUE; 00406 sitter->status = arg; 00407 sitter->errnum = 0; 00408 _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n", 00409 WIFEXITED (sitter->status), WIFSIGNALED (sitter->status), 00410 WEXITSTATUS (sitter->status), WTERMSIG (sitter->status)); 00411 } 00412 else if (what == CHILD_FORK_FAILED) 00413 { 00414 sitter->have_fork_errnum = TRUE; 00415 sitter->errnum = arg; 00416 _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum); 00417 } 00418 else if (what == CHILD_EXEC_FAILED) 00419 { 00420 sitter->have_exec_errnum = TRUE; 00421 sitter->errnum = arg; 00422 _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum); 00423 } 00424 } 00425 } 00426 break; 00427 case CHILD_PID: 00428 { 00429 pid_t pid = -1; 00430 00431 r = read_pid (fd, &pid, &error); 00432 00433 switch (r) 00434 { 00435 case READ_STATUS_ERROR: 00436 _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message); 00437 dbus_error_free (&error); 00438 return r; 00439 case READ_STATUS_EOF: 00440 return r; 00441 case READ_STATUS_OK: 00442 break; 00443 } 00444 00445 sitter->grandchild_pid = pid; 00446 00447 _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid); 00448 } 00449 break; 00450 default: 00451 _dbus_warn ("Unknown message received from babysitter process\n"); 00452 break; 00453 } 00454 } 00455 00456 return r; 00457 } 00458 00459 static void 00460 close_socket_to_babysitter (DBusBabysitter *sitter) 00461 { 00462 _dbus_verbose ("Closing babysitter\n"); 00463 00464 if (sitter->sitter_watch != NULL) 00465 { 00466 _dbus_assert (sitter->watches != NULL); 00467 _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch); 00468 _dbus_watch_invalidate (sitter->sitter_watch); 00469 _dbus_watch_unref (sitter->sitter_watch); 00470 sitter->sitter_watch = NULL; 00471 } 00472 00473 if (sitter->socket_to_babysitter >= 0) 00474 { 00475 _dbus_close_socket (sitter->socket_to_babysitter, NULL); 00476 sitter->socket_to_babysitter = -1; 00477 } 00478 } 00479 00480 static void 00481 close_error_pipe_from_child (DBusBabysitter *sitter) 00482 { 00483 _dbus_verbose ("Closing child error\n"); 00484 00485 if (sitter->error_watch != NULL) 00486 { 00487 _dbus_assert (sitter->watches != NULL); 00488 _dbus_watch_list_remove_watch (sitter->watches, sitter->error_watch); 00489 _dbus_watch_invalidate (sitter->error_watch); 00490 _dbus_watch_unref (sitter->error_watch); 00491 sitter->error_watch = NULL; 00492 } 00493 00494 if (sitter->error_pipe_from_child >= 0) 00495 { 00496 _dbus_close_socket (sitter->error_pipe_from_child, NULL); 00497 sitter->error_pipe_from_child = -1; 00498 } 00499 } 00500 00501 static void 00502 handle_babysitter_socket (DBusBabysitter *sitter, 00503 int revents) 00504 { 00505 /* Even if we have POLLHUP, we want to keep reading 00506 * data until POLLIN goes away; so this function only 00507 * looks at HUP/ERR if no IN is set. 00508 */ 00509 if (revents & _DBUS_POLLIN) 00510 { 00511 _dbus_verbose ("Reading data from babysitter\n"); 00512 if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK) 00513 close_socket_to_babysitter (sitter); 00514 } 00515 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP)) 00516 { 00517 close_socket_to_babysitter (sitter); 00518 } 00519 } 00520 00521 static void 00522 handle_error_pipe (DBusBabysitter *sitter, 00523 int revents) 00524 { 00525 if (revents & _DBUS_POLLIN) 00526 { 00527 _dbus_verbose ("Reading data from child error\n"); 00528 if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK) 00529 close_error_pipe_from_child (sitter); 00530 } 00531 else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP)) 00532 { 00533 close_error_pipe_from_child (sitter); 00534 } 00535 } 00536 00537 /* returns whether there were any poll events handled */ 00538 static dbus_bool_t 00539 babysitter_iteration (DBusBabysitter *sitter, 00540 dbus_bool_t block) 00541 { 00542 DBusPollFD fds[2]; 00543 int i; 00544 dbus_bool_t descriptors_ready; 00545 00546 descriptors_ready = FALSE; 00547 00548 i = 0; 00549 00550 if (sitter->error_pipe_from_child >= 0) 00551 { 00552 fds[i].fd = sitter->error_pipe_from_child; 00553 fds[i].events = _DBUS_POLLIN; 00554 fds[i].revents = 0; 00555 ++i; 00556 } 00557 00558 if (sitter->socket_to_babysitter >= 0) 00559 { 00560 fds[i].fd = sitter->socket_to_babysitter; 00561 fds[i].events = _DBUS_POLLIN; 00562 fds[i].revents = 0; 00563 ++i; 00564 } 00565 00566 if (i > 0) 00567 { 00568 int ret; 00569 00570 do 00571 { 00572 ret = _dbus_poll (fds, i, 0); 00573 } 00574 while (ret < 0 && errno == EINTR); 00575 00576 if (ret == 0 && block) 00577 { 00578 do 00579 { 00580 ret = _dbus_poll (fds, i, -1); 00581 } 00582 while (ret < 0 && errno == EINTR); 00583 } 00584 00585 if (ret > 0) 00586 { 00587 descriptors_ready = TRUE; 00588 00589 while (i > 0) 00590 { 00591 --i; 00592 if (fds[i].fd == sitter->error_pipe_from_child) 00593 handle_error_pipe (sitter, fds[i].revents); 00594 else if (fds[i].fd == sitter->socket_to_babysitter) 00595 handle_babysitter_socket (sitter, fds[i].revents); 00596 } 00597 } 00598 } 00599 00600 return descriptors_ready; 00601 } 00602 00607 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0) 00608 00615 void 00616 _dbus_babysitter_kill_child (DBusBabysitter *sitter) 00617 { 00618 /* be sure we have the PID of the child */ 00619 while (LIVE_CHILDREN (sitter) && 00620 sitter->grandchild_pid == -1) 00621 babysitter_iteration (sitter, TRUE); 00622 00623 _dbus_verbose ("Got child PID %ld for killing\n", 00624 (long) sitter->grandchild_pid); 00625 00626 if (sitter->grandchild_pid == -1) 00627 return; /* child is already dead, or we're so hosed we'll never recover */ 00628 00629 kill (sitter->grandchild_pid, SIGKILL); 00630 } 00631 00637 dbus_bool_t 00638 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter) 00639 { 00640 00641 /* Be sure we're up-to-date */ 00642 while (LIVE_CHILDREN (sitter) && 00643 babysitter_iteration (sitter, FALSE)) 00644 ; 00645 00646 /* We will have exited the babysitter when the child has exited */ 00647 return sitter->socket_to_babysitter < 0; 00648 } 00649 00662 dbus_bool_t 00663 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter, 00664 int *status) 00665 { 00666 if (!_dbus_babysitter_get_child_exited (sitter)) 00667 _dbus_assert_not_reached ("Child has not exited"); 00668 00669 if (!sitter->have_child_status || 00670 !(WIFEXITED (sitter->status))) 00671 return FALSE; 00672 00673 *status = WEXITSTATUS (sitter->status); 00674 return TRUE; 00675 } 00676 00686 void 00687 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter, 00688 DBusError *error) 00689 { 00690 if (!_dbus_babysitter_get_child_exited (sitter)) 00691 return; 00692 00693 /* Note that if exec fails, we will also get a child status 00694 * from the babysitter saying the child exited, 00695 * so we need to give priority to the exec error 00696 */ 00697 if (sitter->have_exec_errnum) 00698 { 00699 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 00700 "Failed to execute program %s: %s", 00701 sitter->executable, _dbus_strerror (sitter->errnum)); 00702 } 00703 else if (sitter->have_fork_errnum) 00704 { 00705 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 00706 "Failed to fork a new process %s: %s", 00707 sitter->executable, _dbus_strerror (sitter->errnum)); 00708 } 00709 else if (sitter->have_child_status) 00710 { 00711 if (WIFEXITED (sitter->status)) 00712 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED, 00713 "Process %s exited with status %d", 00714 sitter->executable, WEXITSTATUS (sitter->status)); 00715 else if (WIFSIGNALED (sitter->status)) 00716 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED, 00717 "Process %s received signal %d", 00718 sitter->executable, WTERMSIG (sitter->status)); 00719 else 00720 dbus_set_error (error, DBUS_ERROR_FAILED, 00721 "Process %s exited abnormally", 00722 sitter->executable); 00723 } 00724 else 00725 { 00726 dbus_set_error (error, DBUS_ERROR_FAILED, 00727 "Process %s exited, reason unknown", 00728 sitter->executable); 00729 } 00730 } 00731 00744 dbus_bool_t 00745 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter, 00746 DBusAddWatchFunction add_function, 00747 DBusRemoveWatchFunction remove_function, 00748 DBusWatchToggledFunction toggled_function, 00749 void *data, 00750 DBusFreeFunction free_data_function) 00751 { 00752 return _dbus_watch_list_set_functions (sitter->watches, 00753 add_function, 00754 remove_function, 00755 toggled_function, 00756 data, 00757 free_data_function); 00758 } 00759 00760 static dbus_bool_t 00761 handle_watch (DBusWatch *watch, 00762 unsigned int condition, 00763 void *data) 00764 { 00765 DBusBabysitter *sitter = _dbus_babysitter_ref (data); 00766 int revents; 00767 int fd; 00768 00769 revents = 0; 00770 if (condition & DBUS_WATCH_READABLE) 00771 revents |= _DBUS_POLLIN; 00772 if (condition & DBUS_WATCH_ERROR) 00773 revents |= _DBUS_POLLERR; 00774 if (condition & DBUS_WATCH_HANGUP) 00775 revents |= _DBUS_POLLHUP; 00776 00777 fd = dbus_watch_get_socket (watch); 00778 00779 if (fd == sitter->error_pipe_from_child) 00780 handle_error_pipe (sitter, revents); 00781 else if (fd == sitter->socket_to_babysitter) 00782 handle_babysitter_socket (sitter, revents); 00783 00784 while (LIVE_CHILDREN (sitter) && 00785 babysitter_iteration (sitter, FALSE)) 00786 ; 00787 00788 /* fd.o #32992: if the handle_* methods closed their sockets, they previously 00789 * didn't always remove the watches. Check that we don't regress. */ 00790 _dbus_assert (sitter->socket_to_babysitter != -1 || sitter->sitter_watch == NULL); 00791 _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL); 00792 00793 if (_dbus_babysitter_get_child_exited (sitter) && 00794 sitter->finished_cb != NULL) 00795 { 00796 sitter->finished_cb (sitter, sitter->finished_data); 00797 sitter->finished_cb = NULL; 00798 } 00799 00800 _dbus_babysitter_unref (sitter); 00801 return TRUE; 00802 } 00803 00805 #define READ_END 0 00806 00807 #define WRITE_END 1 00808 00809 00810 /* Avoids a danger in threaded situations (calling close() 00811 * on a file descriptor twice, and another thread has 00812 * re-opened it since the first close) 00813 */ 00814 static int 00815 close_and_invalidate (int *fd) 00816 { 00817 int ret; 00818 00819 if (*fd < 0) 00820 return -1; 00821 else 00822 { 00823 ret = _dbus_close_socket (*fd, NULL); 00824 *fd = -1; 00825 } 00826 00827 return ret; 00828 } 00829 00830 static dbus_bool_t 00831 make_pipe (int p[2], 00832 DBusError *error) 00833 { 00834 int retval; 00835 00836 #ifdef HAVE_PIPE2 00837 dbus_bool_t cloexec_done; 00838 00839 retval = pipe2 (p, O_CLOEXEC); 00840 cloexec_done = retval >= 0; 00841 00842 /* Check if kernel seems to be too old to know pipe2(). We assume 00843 that if pipe2 is available, O_CLOEXEC is too. */ 00844 if (retval < 0 && errno == ENOSYS) 00845 #endif 00846 { 00847 retval = pipe(p); 00848 } 00849 00850 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00851 00852 if (retval < 0) 00853 { 00854 dbus_set_error (error, 00855 DBUS_ERROR_SPAWN_FAILED, 00856 "Failed to create pipe for communicating with child process (%s)", 00857 _dbus_strerror (errno)); 00858 return FALSE; 00859 } 00860 00861 #ifdef HAVE_PIPE2 00862 if (!cloexec_done) 00863 #endif 00864 { 00865 _dbus_fd_set_close_on_exec (p[0]); 00866 _dbus_fd_set_close_on_exec (p[1]); 00867 } 00868 00869 return TRUE; 00870 } 00871 00872 static void 00873 do_write (int fd, const void *buf, size_t count) 00874 { 00875 size_t bytes_written; 00876 int ret; 00877 00878 bytes_written = 0; 00879 00880 again: 00881 00882 ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written); 00883 00884 if (ret < 0) 00885 { 00886 if (errno == EINTR) 00887 goto again; 00888 else 00889 { 00890 _dbus_warn ("Failed to write data to pipe!\n"); 00891 exit (1); /* give up, we suck */ 00892 } 00893 } 00894 else 00895 bytes_written += ret; 00896 00897 if (bytes_written < count) 00898 goto again; 00899 } 00900 00901 static void 00902 write_err_and_exit (int fd, int msg) 00903 { 00904 int en = errno; 00905 00906 do_write (fd, &msg, sizeof (msg)); 00907 do_write (fd, &en, sizeof (en)); 00908 00909 exit (1); 00910 } 00911 00912 static void 00913 write_pid (int fd, pid_t pid) 00914 { 00915 int msg = CHILD_PID; 00916 00917 do_write (fd, &msg, sizeof (msg)); 00918 do_write (fd, &pid, sizeof (pid)); 00919 } 00920 00921 static void 00922 write_status_and_exit (int fd, int status) 00923 { 00924 int msg = CHILD_EXITED; 00925 00926 do_write (fd, &msg, sizeof (msg)); 00927 do_write (fd, &status, sizeof (status)); 00928 00929 exit (0); 00930 } 00931 00932 static void 00933 do_exec (int child_err_report_fd, 00934 char **argv, 00935 char **envp, 00936 DBusSpawnChildSetupFunc child_setup, 00937 void *user_data) 00938 { 00939 #ifdef DBUS_BUILD_TESTS 00940 int i, max_open; 00941 #endif 00942 00943 _dbus_verbose_reset (); 00944 _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n", 00945 _dbus_getpid ()); 00946 00947 if (child_setup) 00948 (* child_setup) (user_data); 00949 00950 #ifdef DBUS_BUILD_TESTS 00951 max_open = sysconf (_SC_OPEN_MAX); 00952 00953 for (i = 3; i < max_open; i++) 00954 { 00955 int retval; 00956 00957 if (i == child_err_report_fd) 00958 continue; 00959 00960 retval = fcntl (i, F_GETFD); 00961 00962 if (retval != -1 && !(retval & FD_CLOEXEC)) 00963 _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i); 00964 } 00965 #endif 00966 00967 if (envp == NULL) 00968 { 00969 _dbus_assert (environ != NULL); 00970 00971 envp = environ; 00972 } 00973 00974 execve (argv[0], argv, envp); 00975 00976 /* Exec failed */ 00977 write_err_and_exit (child_err_report_fd, 00978 CHILD_EXEC_FAILED); 00979 } 00980 00981 static void 00982 check_babysit_events (pid_t grandchild_pid, 00983 int parent_pipe, 00984 int revents) 00985 { 00986 pid_t ret; 00987 int status; 00988 00989 do 00990 { 00991 ret = waitpid (grandchild_pid, &status, WNOHANG); 00992 /* The man page says EINTR can't happen with WNOHANG, 00993 * but there are reports of it (maybe only with valgrind?) 00994 */ 00995 } 00996 while (ret < 0 && errno == EINTR); 00997 00998 if (ret == 0) 00999 { 01000 _dbus_verbose ("no child exited\n"); 01001 01002 ; /* no child exited */ 01003 } 01004 else if (ret < 0) 01005 { 01006 /* This isn't supposed to happen. */ 01007 _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n", 01008 _dbus_strerror (errno)); 01009 exit (1); 01010 } 01011 else if (ret == grandchild_pid) 01012 { 01013 /* Child exited */ 01014 _dbus_verbose ("reaped child pid %ld\n", (long) ret); 01015 01016 write_status_and_exit (parent_pipe, status); 01017 } 01018 else 01019 { 01020 _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n", 01021 (int) ret); 01022 exit (1); 01023 } 01024 01025 if (revents & _DBUS_POLLIN) 01026 { 01027 _dbus_verbose ("babysitter got POLLIN from parent pipe\n"); 01028 } 01029 01030 if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP)) 01031 { 01032 /* Parent is gone, so we just exit */ 01033 _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n"); 01034 exit (0); 01035 } 01036 } 01037 01038 static int babysit_sigchld_pipe = -1; 01039 01040 static void 01041 babysit_signal_handler (int signo) 01042 { 01043 char b = '\0'; 01044 again: 01045 if (write (babysit_sigchld_pipe, &b, 1) <= 0) 01046 if (errno == EINTR) 01047 goto again; 01048 } 01049 01050 static void 01051 babysit (pid_t grandchild_pid, 01052 int parent_pipe) 01053 { 01054 int sigchld_pipe[2]; 01055 01056 /* We don't exec, so we keep parent state, such as the pid that 01057 * _dbus_verbose() uses. Reset the pid here. 01058 */ 01059 _dbus_verbose_reset (); 01060 01061 /* I thought SIGCHLD would just wake up the poll, but 01062 * that didn't seem to work, so added this pipe. 01063 * Probably the pipe is more likely to work on busted 01064 * operating systems anyhow. 01065 */ 01066 if (pipe (sigchld_pipe) < 0) 01067 { 01068 _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n"); 01069 exit (1); 01070 } 01071 01072 babysit_sigchld_pipe = sigchld_pipe[WRITE_END]; 01073 01074 _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler); 01075 01076 write_pid (parent_pipe, grandchild_pid); 01077 01078 check_babysit_events (grandchild_pid, parent_pipe, 0); 01079 01080 while (TRUE) 01081 { 01082 DBusPollFD pfds[2]; 01083 01084 pfds[0].fd = parent_pipe; 01085 pfds[0].events = _DBUS_POLLIN; 01086 pfds[0].revents = 0; 01087 01088 pfds[1].fd = sigchld_pipe[READ_END]; 01089 pfds[1].events = _DBUS_POLLIN; 01090 pfds[1].revents = 0; 01091 01092 if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR) 01093 { 01094 _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno)); 01095 exit (1); 01096 } 01097 01098 if (pfds[0].revents != 0) 01099 { 01100 check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents); 01101 } 01102 else if (pfds[1].revents & _DBUS_POLLIN) 01103 { 01104 char b; 01105 if (read (sigchld_pipe[READ_END], &b, 1) == -1) 01106 { 01107 /* ignore */ 01108 } 01109 /* do waitpid check */ 01110 check_babysit_events (grandchild_pid, parent_pipe, 0); 01111 } 01112 } 01113 01114 exit (1); 01115 } 01116 01136 dbus_bool_t 01137 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, 01138 char **argv, 01139 char **env, 01140 DBusSpawnChildSetupFunc child_setup, 01141 void *user_data, 01142 DBusError *error) 01143 { 01144 DBusBabysitter *sitter; 01145 int child_err_report_pipe[2] = { -1, -1 }; 01146 int babysitter_pipe[2] = { -1, -1 }; 01147 pid_t pid; 01148 01149 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01150 01151 if (sitter_p != NULL) 01152 *sitter_p = NULL; 01153 01154 sitter = NULL; 01155 01156 sitter = _dbus_babysitter_new (); 01157 if (sitter == NULL) 01158 { 01159 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01160 return FALSE; 01161 } 01162 01163 sitter->executable = _dbus_strdup (argv[0]); 01164 if (sitter->executable == NULL) 01165 { 01166 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01167 goto cleanup_and_fail; 01168 } 01169 01170 if (!make_pipe (child_err_report_pipe, error)) 01171 goto cleanup_and_fail; 01172 01173 if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error)) 01174 goto cleanup_and_fail; 01175 01176 /* Setting up the babysitter is only useful in the parent, 01177 * but we don't want to run out of memory and fail 01178 * after we've already forked, since then we'd leak 01179 * child processes everywhere. 01180 */ 01181 sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END], 01182 DBUS_WATCH_READABLE, 01183 TRUE, handle_watch, sitter, NULL); 01184 if (sitter->error_watch == NULL) 01185 { 01186 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01187 goto cleanup_and_fail; 01188 } 01189 01190 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch)) 01191 { 01192 /* we need to free it early so the destructor won't try to remove it 01193 * without it having been added, which DBusLoop doesn't allow */ 01194 _dbus_watch_invalidate (sitter->error_watch); 01195 _dbus_watch_unref (sitter->error_watch); 01196 sitter->error_watch = NULL; 01197 01198 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01199 goto cleanup_and_fail; 01200 } 01201 01202 sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0], 01203 DBUS_WATCH_READABLE, 01204 TRUE, handle_watch, sitter, NULL); 01205 if (sitter->sitter_watch == NULL) 01206 { 01207 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01208 goto cleanup_and_fail; 01209 } 01210 01211 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch)) 01212 { 01213 /* we need to free it early so the destructor won't try to remove it 01214 * without it having been added, which DBusLoop doesn't allow */ 01215 _dbus_watch_invalidate (sitter->sitter_watch); 01216 _dbus_watch_unref (sitter->sitter_watch); 01217 sitter->sitter_watch = NULL; 01218 01219 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01220 goto cleanup_and_fail; 01221 } 01222 01223 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01224 01225 pid = fork (); 01226 01227 if (pid < 0) 01228 { 01229 dbus_set_error (error, 01230 DBUS_ERROR_SPAWN_FORK_FAILED, 01231 "Failed to fork (%s)", 01232 _dbus_strerror (errno)); 01233 goto cleanup_and_fail; 01234 } 01235 else if (pid == 0) 01236 { 01237 /* Immediate child, this is the babysitter process. */ 01238 int grandchild_pid; 01239 01240 /* Be sure we crash if the parent exits 01241 * and we write to the err_report_pipe 01242 */ 01243 signal (SIGPIPE, SIG_DFL); 01244 01245 /* Close the parent's end of the pipes. */ 01246 close_and_invalidate (&child_err_report_pipe[READ_END]); 01247 close_and_invalidate (&babysitter_pipe[0]); 01248 01249 /* Create the child that will exec () */ 01250 grandchild_pid = fork (); 01251 01252 if (grandchild_pid < 0) 01253 { 01254 write_err_and_exit (babysitter_pipe[1], 01255 CHILD_FORK_FAILED); 01256 _dbus_assert_not_reached ("Got to code after write_err_and_exit()"); 01257 } 01258 else if (grandchild_pid == 0) 01259 { 01260 /* Go back to ignoring SIGPIPE, since it's evil 01261 */ 01262 signal (SIGPIPE, SIG_IGN); 01263 01264 do_exec (child_err_report_pipe[WRITE_END], 01265 argv, 01266 env, 01267 child_setup, user_data); 01268 _dbus_assert_not_reached ("Got to code after exec() - should have exited on error"); 01269 } 01270 else 01271 { 01272 babysit (grandchild_pid, babysitter_pipe[1]); 01273 _dbus_assert_not_reached ("Got to code after babysit()"); 01274 } 01275 } 01276 else 01277 { 01278 /* Close the uncared-about ends of the pipes */ 01279 close_and_invalidate (&child_err_report_pipe[WRITE_END]); 01280 close_and_invalidate (&babysitter_pipe[1]); 01281 01282 sitter->socket_to_babysitter = babysitter_pipe[0]; 01283 babysitter_pipe[0] = -1; 01284 01285 sitter->error_pipe_from_child = child_err_report_pipe[READ_END]; 01286 child_err_report_pipe[READ_END] = -1; 01287 01288 sitter->sitter_pid = pid; 01289 01290 if (sitter_p != NULL) 01291 *sitter_p = sitter; 01292 else 01293 _dbus_babysitter_unref (sitter); 01294 01295 dbus_free_string_array (env); 01296 01297 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01298 01299 return TRUE; 01300 } 01301 01302 cleanup_and_fail: 01303 01304 _DBUS_ASSERT_ERROR_IS_SET (error); 01305 01306 close_and_invalidate (&child_err_report_pipe[READ_END]); 01307 close_and_invalidate (&child_err_report_pipe[WRITE_END]); 01308 close_and_invalidate (&babysitter_pipe[0]); 01309 close_and_invalidate (&babysitter_pipe[1]); 01310 01311 if (sitter != NULL) 01312 _dbus_babysitter_unref (sitter); 01313 01314 return FALSE; 01315 } 01316 01317 void 01318 _dbus_babysitter_set_result_function (DBusBabysitter *sitter, 01319 DBusBabysitterFinishedFunc finished, 01320 void *user_data) 01321 { 01322 sitter->finished_cb = finished; 01323 sitter->finished_data = user_data; 01324 } 01325 01328 #ifdef DBUS_BUILD_TESTS 01329 01330 static char * 01331 get_test_exec (const char *exe, 01332 DBusString *scratch_space) 01333 { 01334 const char *dbus_test_exec; 01335 01336 dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC"); 01337 01338 if (dbus_test_exec == NULL) 01339 dbus_test_exec = DBUS_TEST_EXEC; 01340 01341 if (!_dbus_string_init (scratch_space)) 01342 return NULL; 01343 01344 if (!_dbus_string_append_printf (scratch_space, "%s/%s%s", 01345 dbus_test_exec, exe, DBUS_EXEEXT)) 01346 { 01347 _dbus_string_free (scratch_space); 01348 return NULL; 01349 } 01350 01351 return _dbus_string_get_data (scratch_space); 01352 } 01353 01354 static void 01355 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter) 01356 { 01357 while (LIVE_CHILDREN (sitter)) 01358 babysitter_iteration (sitter, TRUE); 01359 } 01360 01361 static dbus_bool_t 01362 check_spawn_nonexistent (void *data) 01363 { 01364 char *argv[4] = { NULL, NULL, NULL, NULL }; 01365 DBusBabysitter *sitter = NULL; 01366 DBusError error = DBUS_ERROR_INIT; 01367 01368 /*** Test launching nonexistent binary */ 01369 01370 argv[0] = "/this/does/not/exist/32542sdgafgafdg"; 01371 if (_dbus_spawn_async_with_babysitter (&sitter, argv, 01372 NULL, NULL, NULL, 01373 &error)) 01374 { 01375 _dbus_babysitter_block_for_child_exit (sitter); 01376 _dbus_babysitter_set_child_exit_error (sitter, &error); 01377 } 01378 01379 if (sitter) 01380 _dbus_babysitter_unref (sitter); 01381 01382 if (!dbus_error_is_set (&error)) 01383 { 01384 _dbus_warn ("Did not get an error launching nonexistent executable\n"); 01385 return FALSE; 01386 } 01387 01388 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || 01389 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED))) 01390 { 01391 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n", 01392 error.name, error.message); 01393 dbus_error_free (&error); 01394 return FALSE; 01395 } 01396 01397 dbus_error_free (&error); 01398 01399 return TRUE; 01400 } 01401 01402 static dbus_bool_t 01403 check_spawn_segfault (void *data) 01404 { 01405 char *argv[4] = { NULL, NULL, NULL, NULL }; 01406 DBusBabysitter *sitter = NULL; 01407 DBusError error = DBUS_ERROR_INIT; 01408 DBusString argv0; 01409 01410 /*** Test launching segfault binary */ 01411 01412 argv[0] = get_test_exec ("test-segfault", &argv0); 01413 01414 if (argv[0] == NULL) 01415 { 01416 /* OOM was simulated, never mind */ 01417 return TRUE; 01418 } 01419 01420 if (_dbus_spawn_async_with_babysitter (&sitter, argv, 01421 NULL, NULL, NULL, 01422 &error)) 01423 { 01424 _dbus_babysitter_block_for_child_exit (sitter); 01425 _dbus_babysitter_set_child_exit_error (sitter, &error); 01426 } 01427 01428 _dbus_string_free (&argv0); 01429 01430 if (sitter) 01431 _dbus_babysitter_unref (sitter); 01432 01433 if (!dbus_error_is_set (&error)) 01434 { 01435 _dbus_warn ("Did not get an error launching segfaulting binary\n"); 01436 return FALSE; 01437 } 01438 01439 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || 01440 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED))) 01441 { 01442 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n", 01443 error.name, error.message); 01444 dbus_error_free (&error); 01445 return FALSE; 01446 } 01447 01448 dbus_error_free (&error); 01449 01450 return TRUE; 01451 } 01452 01453 static dbus_bool_t 01454 check_spawn_exit (void *data) 01455 { 01456 char *argv[4] = { NULL, NULL, NULL, NULL }; 01457 DBusBabysitter *sitter = NULL; 01458 DBusError error = DBUS_ERROR_INIT; 01459 DBusString argv0; 01460 01461 /*** Test launching exit failure binary */ 01462 01463 argv[0] = get_test_exec ("test-exit", &argv0); 01464 01465 if (argv[0] == NULL) 01466 { 01467 /* OOM was simulated, never mind */ 01468 return TRUE; 01469 } 01470 01471 if (_dbus_spawn_async_with_babysitter (&sitter, argv, 01472 NULL, NULL, NULL, 01473 &error)) 01474 { 01475 _dbus_babysitter_block_for_child_exit (sitter); 01476 _dbus_babysitter_set_child_exit_error (sitter, &error); 01477 } 01478 01479 _dbus_string_free (&argv0); 01480 01481 if (sitter) 01482 _dbus_babysitter_unref (sitter); 01483 01484 if (!dbus_error_is_set (&error)) 01485 { 01486 _dbus_warn ("Did not get an error launching binary that exited with failure code\n"); 01487 return FALSE; 01488 } 01489 01490 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || 01491 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED))) 01492 { 01493 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n", 01494 error.name, error.message); 01495 dbus_error_free (&error); 01496 return FALSE; 01497 } 01498 01499 dbus_error_free (&error); 01500 01501 return TRUE; 01502 } 01503 01504 static dbus_bool_t 01505 check_spawn_and_kill (void *data) 01506 { 01507 char *argv[4] = { NULL, NULL, NULL, NULL }; 01508 DBusBabysitter *sitter = NULL; 01509 DBusError error = DBUS_ERROR_INIT; 01510 DBusString argv0; 01511 01512 /*** Test launching sleeping binary then killing it */ 01513 01514 argv[0] = get_test_exec ("test-sleep-forever", &argv0); 01515 01516 if (argv[0] == NULL) 01517 { 01518 /* OOM was simulated, never mind */ 01519 return TRUE; 01520 } 01521 01522 if (_dbus_spawn_async_with_babysitter (&sitter, argv, 01523 NULL, NULL, NULL, 01524 &error)) 01525 { 01526 _dbus_babysitter_kill_child (sitter); 01527 01528 _dbus_babysitter_block_for_child_exit (sitter); 01529 01530 _dbus_babysitter_set_child_exit_error (sitter, &error); 01531 } 01532 01533 _dbus_string_free (&argv0); 01534 01535 if (sitter) 01536 _dbus_babysitter_unref (sitter); 01537 01538 if (!dbus_error_is_set (&error)) 01539 { 01540 _dbus_warn ("Did not get an error after killing spawned binary\n"); 01541 return FALSE; 01542 } 01543 01544 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || 01545 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED))) 01546 { 01547 _dbus_warn ("Not expecting error when killing executable: %s: %s\n", 01548 error.name, error.message); 01549 dbus_error_free (&error); 01550 return FALSE; 01551 } 01552 01553 dbus_error_free (&error); 01554 01555 return TRUE; 01556 } 01557 01558 dbus_bool_t 01559 _dbus_spawn_test (const char *test_data_dir) 01560 { 01561 if (!_dbus_test_oom_handling ("spawn_nonexistent", 01562 check_spawn_nonexistent, 01563 NULL)) 01564 return FALSE; 01565 01566 if (!_dbus_test_oom_handling ("spawn_segfault", 01567 check_spawn_segfault, 01568 NULL)) 01569 return FALSE; 01570 01571 if (!_dbus_test_oom_handling ("spawn_exit", 01572 check_spawn_exit, 01573 NULL)) 01574 return FALSE; 01575 01576 if (!_dbus_test_oom_handling ("spawn_and_kill", 01577 check_spawn_and_kill, 01578 NULL)) 01579 return FALSE; 01580 01581 return TRUE; 01582 } 01583 #endif