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