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