D-Bus  1.8.20
dbus-spawn.c
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 #ifdef HAVE_SYSTEMD
00042 #ifdef HAVE_SYSLOG_H
00043 #include <syslog.h>
00044 #endif
00045 #include <systemd/sd-journal.h>
00046 #endif
00047 
00048 extern char **environ;
00049 
00055 /*
00056  * I'm pretty sure this whole spawn file could be made simpler,
00057  * if you thought about it a bit.
00058  */
00059 
00063 typedef enum
00064 {
00065   READ_STATUS_OK,    
00066   READ_STATUS_ERROR, 
00067   READ_STATUS_EOF    
00068 } ReadStatus;
00069 
00070 static ReadStatus
00071 read_ints (int        fd,
00072            int       *buf,
00073            int        n_ints_in_buf,
00074            int       *n_ints_read,
00075            DBusError *error)
00076 {
00077   size_t bytes = 0;    
00078   ReadStatus retval;
00079   
00080   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00081 
00082   retval = READ_STATUS_OK;
00083   
00084   while (TRUE)
00085     {
00086       ssize_t chunk;
00087       size_t to_read;
00088 
00089       to_read = sizeof (int) * n_ints_in_buf - bytes;
00090 
00091       if (to_read == 0)
00092         break;
00093 
00094     again:
00095       
00096       chunk = read (fd,
00097                     ((char*)buf) + bytes,
00098                     to_read);
00099       
00100       if (chunk < 0 && errno == EINTR)
00101         goto again;
00102           
00103       if (chunk < 0)
00104         {
00105           dbus_set_error (error,
00106                           DBUS_ERROR_SPAWN_FAILED,
00107                           "Failed to read from child pipe (%s)",
00108                           _dbus_strerror (errno));
00109 
00110           retval = READ_STATUS_ERROR;
00111           break;
00112         }
00113       else if (chunk == 0)
00114         {
00115           retval = READ_STATUS_EOF;
00116           break; /* EOF */
00117         }
00118       else /* chunk > 0 */
00119         bytes += chunk;
00120     }
00121 
00122   *n_ints_read = (int)(bytes / sizeof(int));
00123 
00124   return retval;
00125 }
00126 
00127 static ReadStatus
00128 read_pid (int        fd,
00129           pid_t     *buf,
00130           DBusError *error)
00131 {
00132   size_t bytes = 0;    
00133   ReadStatus retval;
00134   
00135   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00136 
00137   retval = READ_STATUS_OK;
00138   
00139   while (TRUE)
00140     {
00141       ssize_t chunk;
00142       size_t to_read;
00143 
00144       to_read = sizeof (pid_t) - bytes;
00145 
00146       if (to_read == 0)
00147         break;
00148 
00149     again:
00150       
00151       chunk = read (fd,
00152                     ((char*)buf) + bytes,
00153                     to_read);
00154       if (chunk < 0 && errno == EINTR)
00155         goto again;
00156           
00157       if (chunk < 0)
00158         {
00159           dbus_set_error (error,
00160                           DBUS_ERROR_SPAWN_FAILED,
00161                           "Failed to read from child pipe (%s)",
00162                           _dbus_strerror (errno));
00163 
00164           retval = READ_STATUS_ERROR;
00165           break;
00166         }
00167       else if (chunk == 0)
00168         {
00169           retval = READ_STATUS_EOF;
00170           break; /* EOF */
00171         }
00172       else /* chunk > 0 */
00173         bytes += chunk;
00174     }
00175 
00176   return retval;
00177 }
00178 
00179 /* The implementation uses an intermediate child between the main process
00180  * and the grandchild. The grandchild is our spawned process. The intermediate
00181  * child is a babysitter process; it keeps track of when the grandchild
00182  * exits/crashes, and reaps the grandchild.
00183  *
00184  * We automatically reap the babysitter process, killing it if necessary,
00185  * when the DBusBabysitter's refcount goes to zero.
00186  *
00187  * Processes:
00188  *
00189  * main process
00190  * | fork() A
00191  * \- babysitter
00192  *    | fork () B
00193  *    \- grandchild     --> exec -->    spawned process
00194  *
00195  * IPC:
00196  *                  child_err_report_pipe
00197  *          /-----------<---------<--------------\
00198  *          |                                    ^
00199  *          v                                    |
00200  * main process           babysitter          grandchild
00201  *          ^                 ^
00202  *          v                 v
00203  *          \-------<->-------/
00204  *            babysitter_pipe
00205  *
00206  * child_err_report_pipe is genuinely a pipe.
00207  * The READ_END (also called error_pipe_from_child) is used in the main
00208  * process. The WRITE_END (also called child_err_report_fd) is used in
00209  * the grandchild process.
00210  *
00211  * On failure, the grandchild process sends CHILD_EXEC_FAILED + errno.
00212  * On success, the pipe just closes (because it's close-on-exec) without
00213  * sending any bytes.
00214  *
00215  * babysitter_pipe is mis-named: it's really a bidirectional socketpair.
00216  * The [0] end (also called socket_to_babysitter) is used in the main
00217  * process, the [1] end (also called parent_pipe) is used in the babysitter.
00218  *
00219  * If the fork() labelled B in the diagram above fails, the babysitter sends
00220  * CHILD_FORK_FAILED + errno.
00221  * On success, the babysitter sends CHILD_PID + the grandchild's pid.
00222  * On SIGCHLD, the babysitter sends CHILD_EXITED + the exit status.
00223  * The main process doesn't explicitly send anything, but when it exits,
00224  * the babysitter gets POLLHUP or POLLERR.
00225  */
00226 
00227 /* Messages from children to parents */
00228 enum
00229 {
00230   CHILD_EXITED,            /* This message is followed by the exit status int */
00231   CHILD_FORK_FAILED,       /* Followed by errno */
00232   CHILD_EXEC_FAILED,       /* Followed by errno */
00233   CHILD_PID                /* Followed by pid_t */
00234 };
00235 
00239 struct DBusBabysitter
00240 {
00241   int refcount; 
00243   char *log_name; 
00246   int socket_to_babysitter; 
00247   int error_pipe_from_child; 
00249   pid_t sitter_pid;  
00250   pid_t grandchild_pid; 
00252   DBusWatchList *watches; 
00254   DBusWatch *error_watch; 
00255   DBusWatch *sitter_watch; 
00257   DBusBabysitterFinishedFunc finished_cb;
00258   void *finished_data;
00259 
00260   int errnum; 
00261   int status; 
00262   unsigned int have_child_status : 1; 
00263   unsigned int have_fork_errnum : 1; 
00264   unsigned int have_exec_errnum : 1; 
00265 };
00266 
00267 static DBusBabysitter*
00268 _dbus_babysitter_new (void)
00269 {
00270   DBusBabysitter *sitter;
00271 
00272   sitter = dbus_new0 (DBusBabysitter, 1);
00273   if (sitter == NULL)
00274     return NULL;
00275 
00276   sitter->refcount = 1;
00277 
00278   sitter->socket_to_babysitter = -1;
00279   sitter->error_pipe_from_child = -1;
00280   
00281   sitter->sitter_pid = -1;
00282   sitter->grandchild_pid = -1;
00283 
00284   sitter->watches = _dbus_watch_list_new ();
00285   if (sitter->watches == NULL)
00286     goto failed;
00287   
00288   return sitter;
00289 
00290  failed:
00291   _dbus_babysitter_unref (sitter);
00292   return NULL;
00293 }
00294 
00301 DBusBabysitter *
00302 _dbus_babysitter_ref (DBusBabysitter *sitter)
00303 {
00304   _dbus_assert (sitter != NULL);
00305   _dbus_assert (sitter->refcount > 0);
00306   
00307   sitter->refcount += 1;
00308 
00309   return sitter;
00310 }
00311 
00312 static void close_socket_to_babysitter  (DBusBabysitter *sitter);
00313 static void close_error_pipe_from_child (DBusBabysitter *sitter);
00314 
00323 void
00324 _dbus_babysitter_unref (DBusBabysitter *sitter)
00325 {
00326   _dbus_assert (sitter != NULL);
00327   _dbus_assert (sitter->refcount > 0);
00328   
00329   sitter->refcount -= 1;
00330   if (sitter->refcount == 0)
00331     {
00332       /* If we haven't forked other babysitters
00333        * since this babysitter and socket were
00334        * created then this close will cause the
00335        * babysitter to wake up from poll with
00336        * a hangup and then the babysitter will
00337        * quit itself.
00338        */
00339       close_socket_to_babysitter (sitter);
00340 
00341       close_error_pipe_from_child (sitter);
00342 
00343       if (sitter->sitter_pid > 0)
00344         {
00345           int status;
00346           int ret;
00347 
00348           /* It's possible the babysitter died on its own above 
00349            * from the close, or was killed randomly
00350            * by some other process, so first try to reap it
00351            */
00352           ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
00353 
00354           /* If we couldn't reap the child then kill it, and
00355            * try again
00356            */
00357           if (ret == 0)
00358             kill (sitter->sitter_pid, SIGKILL);
00359 
00360           if (ret == 0)
00361             {
00362               do
00363                 {
00364                   ret = waitpid (sitter->sitter_pid, &status, 0);
00365                 }
00366               while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
00367             }
00368 
00369           if (ret < 0)
00370             {
00371               if (errno == ECHILD)
00372                 _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
00373               else
00374                 _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
00375                             errno, _dbus_strerror (errno));
00376             }
00377           else
00378             {
00379               _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
00380                              (long) ret, (long) sitter->sitter_pid);
00381               
00382               if (WIFEXITED (sitter->status))
00383                 _dbus_verbose ("Babysitter exited with status %d\n",
00384                                WEXITSTATUS (sitter->status));
00385               else if (WIFSIGNALED (sitter->status))
00386                 _dbus_verbose ("Babysitter received signal %d\n",
00387                                WTERMSIG (sitter->status));
00388               else
00389                 _dbus_verbose ("Babysitter exited abnormally\n");
00390             }
00391 
00392           sitter->sitter_pid = -1;
00393         }
00394 
00395       if (sitter->watches)
00396         _dbus_watch_list_free (sitter->watches);
00397 
00398       dbus_free (sitter->log_name);
00399       
00400       dbus_free (sitter);
00401     }
00402 }
00403 
00404 static ReadStatus
00405 read_data (DBusBabysitter *sitter,
00406            int             fd)
00407 {
00408   int what;
00409   int got;
00410   DBusError error = DBUS_ERROR_INIT;
00411   ReadStatus r;
00412 
00413   r = read_ints (fd, &what, 1, &got, &error);
00414 
00415   switch (r)
00416     {
00417     case READ_STATUS_ERROR:
00418       _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
00419       dbus_error_free (&error);
00420       return r;
00421 
00422     case READ_STATUS_EOF:
00423       return r;
00424 
00425     case READ_STATUS_OK:
00426       break;
00427     }
00428   
00429   if (got == 1)
00430     {
00431       switch (what)
00432         {
00433         case CHILD_EXITED:
00434         case CHILD_FORK_FAILED:
00435         case CHILD_EXEC_FAILED:
00436           {
00437             int arg;
00438             
00439             r = read_ints (fd, &arg, 1, &got, &error);
00440 
00441             switch (r)
00442               {
00443               case READ_STATUS_ERROR:
00444                 _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
00445                 dbus_error_free (&error);
00446                 return r;
00447               case READ_STATUS_EOF:
00448                 return r;
00449               case READ_STATUS_OK:
00450                 break;
00451               }
00452             
00453             if (got == 1)
00454               {
00455                 if (what == CHILD_EXITED)
00456                   {
00457                     sitter->have_child_status = TRUE;
00458                     sitter->status = arg;
00459                     sitter->errnum = 0;
00460                     _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
00461                                    WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
00462                                    WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
00463                   }
00464                 else if (what == CHILD_FORK_FAILED)
00465                   {
00466                     sitter->have_fork_errnum = TRUE;
00467                     sitter->errnum = arg;
00468                     _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
00469                   }
00470                 else if (what == CHILD_EXEC_FAILED)
00471                   {
00472                     sitter->have_exec_errnum = TRUE;
00473                     sitter->errnum = arg;
00474                     _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
00475                   }
00476               }
00477           }
00478           break;
00479         case CHILD_PID:
00480           {
00481             pid_t pid = -1;
00482 
00483             r = read_pid (fd, &pid, &error);
00484             
00485             switch (r)
00486               {
00487               case READ_STATUS_ERROR:
00488                 _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
00489                 dbus_error_free (&error);
00490                 return r;
00491               case READ_STATUS_EOF:
00492                 return r;
00493               case READ_STATUS_OK:
00494                 break;
00495               }
00496             
00497             sitter->grandchild_pid = pid;
00498             
00499             _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
00500           }
00501           break;
00502         default:
00503           _dbus_warn ("Unknown message received from babysitter process\n");
00504           break;
00505         }
00506     }
00507 
00508   return r;
00509 }
00510 
00511 static void
00512 close_socket_to_babysitter (DBusBabysitter *sitter)
00513 {
00514   _dbus_verbose ("Closing babysitter\n");
00515 
00516   if (sitter->sitter_watch != NULL)
00517     {
00518       _dbus_assert (sitter->watches != NULL);
00519       _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
00520       _dbus_watch_invalidate (sitter->sitter_watch);
00521       _dbus_watch_unref (sitter->sitter_watch);
00522       sitter->sitter_watch = NULL;
00523     }
00524 
00525   if (sitter->socket_to_babysitter >= 0)
00526     {
00527       _dbus_close_socket (sitter->socket_to_babysitter, NULL);
00528       sitter->socket_to_babysitter = -1;
00529     }
00530 }
00531 
00532 static void
00533 close_error_pipe_from_child (DBusBabysitter *sitter)
00534 {
00535   _dbus_verbose ("Closing child error\n");
00536 
00537   if (sitter->error_watch != NULL)
00538     {
00539       _dbus_assert (sitter->watches != NULL);
00540       _dbus_watch_list_remove_watch (sitter->watches,  sitter->error_watch);
00541       _dbus_watch_invalidate (sitter->error_watch);
00542       _dbus_watch_unref (sitter->error_watch);
00543       sitter->error_watch = NULL;
00544     }
00545 
00546   if (sitter->error_pipe_from_child >= 0)
00547     {
00548       _dbus_close_socket (sitter->error_pipe_from_child, NULL);
00549       sitter->error_pipe_from_child = -1;
00550     }
00551 }
00552 
00553 static void
00554 handle_babysitter_socket (DBusBabysitter *sitter,
00555                           int             revents)
00556 {
00557   /* Even if we have POLLHUP, we want to keep reading
00558    * data until POLLIN goes away; so this function only
00559    * looks at HUP/ERR if no IN is set.
00560    */
00561   if (revents & _DBUS_POLLIN)
00562     {
00563       _dbus_verbose ("Reading data from babysitter\n");
00564       if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK)
00565         close_socket_to_babysitter (sitter);
00566     }
00567   else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00568     {
00569       close_socket_to_babysitter (sitter);
00570     }
00571 }
00572 
00573 static void
00574 handle_error_pipe (DBusBabysitter *sitter,
00575                    int             revents)
00576 {
00577   if (revents & _DBUS_POLLIN)
00578     {
00579       _dbus_verbose ("Reading data from child error\n");
00580       if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
00581         close_error_pipe_from_child (sitter);
00582     }
00583   else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00584     {
00585       close_error_pipe_from_child (sitter);
00586     }
00587 }
00588 
00589 /* returns whether there were any poll events handled */
00590 static dbus_bool_t
00591 babysitter_iteration (DBusBabysitter *sitter,
00592                       dbus_bool_t     block)
00593 {
00594   DBusPollFD fds[2];
00595   int i;
00596   dbus_bool_t descriptors_ready;
00597 
00598   descriptors_ready = FALSE;
00599   
00600   i = 0;
00601 
00602   if (sitter->error_pipe_from_child >= 0)
00603     {
00604       fds[i].fd = sitter->error_pipe_from_child;
00605       fds[i].events = _DBUS_POLLIN;
00606       fds[i].revents = 0;
00607       ++i;
00608     }
00609   
00610   if (sitter->socket_to_babysitter >= 0)
00611     {
00612       fds[i].fd = sitter->socket_to_babysitter;
00613       fds[i].events = _DBUS_POLLIN;
00614       fds[i].revents = 0;
00615       ++i;
00616     }
00617 
00618   if (i > 0)
00619     {
00620       int ret;
00621 
00622       do
00623         {
00624           ret = _dbus_poll (fds, i, 0);
00625         }
00626       while (ret < 0 && errno == EINTR);
00627 
00628       if (ret == 0 && block)
00629         {
00630           do
00631             {
00632               ret = _dbus_poll (fds, i, -1);
00633             }
00634           while (ret < 0 && errno == EINTR);
00635         }
00636 
00637       if (ret > 0)
00638         {
00639           descriptors_ready = TRUE;
00640           
00641           while (i > 0)
00642             {
00643               --i;
00644               if (fds[i].fd == sitter->error_pipe_from_child)
00645                 handle_error_pipe (sitter, fds[i].revents);
00646               else if (fds[i].fd == sitter->socket_to_babysitter)
00647                 handle_babysitter_socket (sitter, fds[i].revents);
00648             }
00649         }
00650     }
00651 
00652   return descriptors_ready;
00653 }
00654 
00659 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
00660 
00667 void
00668 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
00669 {
00670   /* be sure we have the PID of the child */
00671   while (LIVE_CHILDREN (sitter) &&
00672          sitter->grandchild_pid == -1)
00673     babysitter_iteration (sitter, TRUE);
00674 
00675   _dbus_verbose ("Got child PID %ld for killing\n",
00676                  (long) sitter->grandchild_pid);
00677   
00678   if (sitter->grandchild_pid == -1)
00679     return; /* child is already dead, or we're so hosed we'll never recover */
00680 
00681   kill (sitter->grandchild_pid, SIGKILL);
00682 }
00683 
00689 dbus_bool_t
00690 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
00691 {
00692 
00693   /* Be sure we're up-to-date */
00694   while (LIVE_CHILDREN (sitter) &&
00695          babysitter_iteration (sitter, FALSE))
00696     ;
00697 
00698   /* We will have exited the babysitter when the child has exited */
00699   return sitter->socket_to_babysitter < 0;
00700 }
00701 
00714 dbus_bool_t
00715 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
00716                                         int            *status)
00717 {
00718   if (!_dbus_babysitter_get_child_exited (sitter))
00719     _dbus_assert_not_reached ("Child has not exited");
00720   
00721   if (!sitter->have_child_status ||
00722       !(WIFEXITED (sitter->status)))
00723     return FALSE;
00724 
00725   *status = WEXITSTATUS (sitter->status);
00726   return TRUE;
00727 }
00728 
00738 void
00739 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
00740                                        DBusError      *error)
00741 {
00742   if (!_dbus_babysitter_get_child_exited (sitter))
00743     return;
00744 
00745   /* Note that if exec fails, we will also get a child status
00746    * from the babysitter saying the child exited,
00747    * so we need to give priority to the exec error
00748    */
00749   if (sitter->have_exec_errnum)
00750     {
00751       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
00752                       "Failed to execute program %s: %s",
00753                       sitter->log_name, _dbus_strerror (sitter->errnum));
00754     }
00755   else if (sitter->have_fork_errnum)
00756     {
00757       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00758                       "Failed to fork a new process %s: %s",
00759                       sitter->log_name, _dbus_strerror (sitter->errnum));
00760     }
00761   else if (sitter->have_child_status)
00762     {
00763       if (WIFEXITED (sitter->status))
00764         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
00765                         "Process %s exited with status %d",
00766                         sitter->log_name, WEXITSTATUS (sitter->status));
00767       else if (WIFSIGNALED (sitter->status))
00768         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
00769                         "Process %s received signal %d",
00770                         sitter->log_name, WTERMSIG (sitter->status));
00771       else
00772         dbus_set_error (error, DBUS_ERROR_FAILED,
00773                         "Process %s exited abnormally",
00774                         sitter->log_name);
00775     }
00776   else
00777     {
00778       dbus_set_error (error, DBUS_ERROR_FAILED,
00779                       "Process %s exited, reason unknown",
00780                       sitter->log_name);
00781     }
00782 }
00783 
00796 dbus_bool_t
00797 _dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
00798                                       DBusAddWatchFunction       add_function,
00799                                       DBusRemoveWatchFunction    remove_function,
00800                                       DBusWatchToggledFunction   toggled_function,
00801                                       void                      *data,
00802                                       DBusFreeFunction           free_data_function)
00803 {
00804   return _dbus_watch_list_set_functions (sitter->watches,
00805                                          add_function,
00806                                          remove_function,
00807                                          toggled_function,
00808                                          data,
00809                                          free_data_function);
00810 }
00811 
00812 static dbus_bool_t
00813 handle_watch (DBusWatch       *watch,
00814               unsigned int     condition,
00815               void            *data)
00816 {
00817   DBusBabysitter *sitter = _dbus_babysitter_ref (data);
00818   int revents;
00819   int fd;
00820   
00821   revents = 0;
00822   if (condition & DBUS_WATCH_READABLE)
00823     revents |= _DBUS_POLLIN;
00824   if (condition & DBUS_WATCH_ERROR)
00825     revents |= _DBUS_POLLERR;
00826   if (condition & DBUS_WATCH_HANGUP)
00827     revents |= _DBUS_POLLHUP;
00828 
00829   fd = dbus_watch_get_socket (watch);
00830 
00831   if (fd == sitter->error_pipe_from_child)
00832     handle_error_pipe (sitter, revents);
00833   else if (fd == sitter->socket_to_babysitter)
00834     handle_babysitter_socket (sitter, revents);
00835 
00836   while (LIVE_CHILDREN (sitter) &&
00837          babysitter_iteration (sitter, FALSE))
00838     ;
00839 
00840   /* fd.o #32992: if the handle_* methods closed their sockets, they previously
00841    * didn't always remove the watches. Check that we don't regress. */
00842   _dbus_assert (sitter->socket_to_babysitter != -1 || sitter->sitter_watch == NULL);
00843   _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
00844 
00845   if (_dbus_babysitter_get_child_exited (sitter) &&
00846       sitter->finished_cb != NULL)
00847     {
00848       sitter->finished_cb (sitter, sitter->finished_data);
00849       sitter->finished_cb = NULL;
00850     }
00851 
00852   _dbus_babysitter_unref (sitter);
00853   return TRUE;
00854 }
00855 
00857 #define READ_END 0
00858 
00859 #define WRITE_END 1
00860 
00861 
00862 /* Avoids a danger in re-entrant situations (calling close()
00863  * on a file descriptor twice, and another module has
00864  * re-opened it since the first close).
00865  *
00866  * This previously claimed to be relevant for threaded situations, but by
00867  * trivial inspection, it is not thread-safe. It doesn't actually
00868  * matter, since this module is only used in the -util variant of the
00869  * library, which is only used in single-threaded situations.
00870  */
00871 static int
00872 close_and_invalidate (int *fd)
00873 {
00874   int ret;
00875 
00876   if (*fd < 0)
00877     return -1;
00878   else
00879     {
00880       ret = _dbus_close_socket (*fd, NULL);
00881       *fd = -1;
00882     }
00883 
00884   return ret;
00885 }
00886 
00887 static dbus_bool_t
00888 make_pipe (int         p[2],
00889            DBusError  *error)
00890 {
00891   int retval;
00892 
00893 #ifdef HAVE_PIPE2
00894   dbus_bool_t cloexec_done;
00895 
00896   retval = pipe2 (p, O_CLOEXEC);
00897   cloexec_done = retval >= 0;
00898 
00899   /* Check if kernel seems to be too old to know pipe2(). We assume
00900      that if pipe2 is available, O_CLOEXEC is too.  */
00901   if (retval < 0 && errno == ENOSYS)
00902 #endif
00903     {
00904       retval = pipe(p);
00905     }
00906 
00907   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00908 
00909   if (retval < 0)
00910     {
00911       dbus_set_error (error,
00912                       DBUS_ERROR_SPAWN_FAILED,
00913                       "Failed to create pipe for communicating with child process (%s)",
00914                       _dbus_strerror (errno));
00915       return FALSE;
00916     }
00917 
00918 #ifdef HAVE_PIPE2
00919   if (!cloexec_done)
00920 #endif
00921     {
00922       _dbus_fd_set_close_on_exec (p[0]);
00923       _dbus_fd_set_close_on_exec (p[1]);
00924     }
00925 
00926   return TRUE;
00927 }
00928 
00929 static void
00930 do_write (int fd, const void *buf, size_t count)
00931 {
00932   size_t bytes_written;
00933   int ret;
00934   
00935   bytes_written = 0;
00936   
00937  again:
00938   
00939   ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
00940 
00941   if (ret < 0)
00942     {
00943       if (errno == EINTR)
00944         goto again;
00945       else
00946         {
00947           _dbus_warn ("Failed to write data to pipe!\n");
00948           exit (1); /* give up, we suck */
00949         }
00950     }
00951   else
00952     bytes_written += ret;
00953   
00954   if (bytes_written < count)
00955     goto again;
00956 }
00957 
00958 static void
00959 write_err_and_exit (int fd, int msg)
00960 {
00961   int en = errno;
00962 
00963   do_write (fd, &msg, sizeof (msg));
00964   do_write (fd, &en, sizeof (en));
00965   
00966   exit (1);
00967 }
00968 
00969 static void
00970 write_pid (int fd, pid_t pid)
00971 {
00972   int msg = CHILD_PID;
00973   
00974   do_write (fd, &msg, sizeof (msg));
00975   do_write (fd, &pid, sizeof (pid));
00976 }
00977 
00978 static void
00979 write_status_and_exit (int fd, int status)
00980 {
00981   int msg = CHILD_EXITED;
00982   
00983   do_write (fd, &msg, sizeof (msg));
00984   do_write (fd, &status, sizeof (status));
00985   
00986   exit (0);
00987 }
00988 
00989 static void
00990 do_exec (int                       child_err_report_fd,
00991          char                    **argv,
00992          char                    **envp,
00993          DBusSpawnChildSetupFunc   child_setup,
00994          void                     *user_data)
00995 {
00996 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00997   int i, max_open;
00998 #endif
00999 
01000   _dbus_verbose_reset ();
01001   _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
01002                  _dbus_getpid ());
01003   
01004   if (child_setup)
01005     (* child_setup) (user_data);
01006 
01007 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01008   max_open = sysconf (_SC_OPEN_MAX);
01009   
01010   for (i = 3; i < max_open; i++)
01011     {
01012       int retval;
01013 
01014       if (i == child_err_report_fd)
01015         continue;
01016       
01017       retval = fcntl (i, F_GETFD);
01018 
01019       if (retval != -1 && !(retval & FD_CLOEXEC))
01020         _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
01021     }
01022 #endif
01023 
01024   if (envp == NULL)
01025     {
01026       _dbus_assert (environ != NULL);
01027 
01028       envp = environ;
01029     }
01030   
01031   execve (argv[0], argv, envp);
01032   
01033   /* Exec failed */
01034   write_err_and_exit (child_err_report_fd,
01035                       CHILD_EXEC_FAILED);
01036 }
01037 
01038 static void
01039 check_babysit_events (pid_t grandchild_pid,
01040                       int   parent_pipe,
01041                       int   revents)
01042 {
01043   pid_t ret;
01044   int status;
01045   
01046   do
01047     {
01048       ret = waitpid (grandchild_pid, &status, WNOHANG);
01049       /* The man page says EINTR can't happen with WNOHANG,
01050        * but there are reports of it (maybe only with valgrind?)
01051        */
01052     }
01053   while (ret < 0 && errno == EINTR);
01054 
01055   if (ret == 0)
01056     {
01057       _dbus_verbose ("no child exited\n");
01058       
01059       ; /* no child exited */
01060     }
01061   else if (ret < 0)
01062     {
01063       /* This isn't supposed to happen. */
01064       _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
01065                   _dbus_strerror (errno));
01066       exit (1);
01067     }
01068   else if (ret == grandchild_pid)
01069     {
01070       /* Child exited */
01071       _dbus_verbose ("reaped child pid %ld\n", (long) ret);
01072       
01073       write_status_and_exit (parent_pipe, status);
01074     }
01075   else
01076     {
01077       _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
01078                   (int) ret);
01079       exit (1);
01080     }
01081 
01082   if (revents & _DBUS_POLLIN)
01083     {
01084       _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
01085     }
01086 
01087   if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
01088     {
01089       /* Parent is gone, so we just exit */
01090       _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
01091       exit (0);
01092     }
01093 }
01094 
01095 static int babysit_sigchld_pipe = -1;
01096 
01097 static void
01098 babysit_signal_handler (int signo)
01099 {
01100   char b = '\0';
01101  again:
01102   if (write (babysit_sigchld_pipe, &b, 1) <= 0) 
01103     if (errno == EINTR)
01104       goto again;
01105 }
01106 
01107 static void
01108 babysit (pid_t grandchild_pid,
01109          int   parent_pipe)
01110 {
01111   int sigchld_pipe[2];
01112 
01113   /* We don't exec, so we keep parent state, such as the pid that
01114    * _dbus_verbose() uses. Reset the pid here.
01115    */
01116   _dbus_verbose_reset ();
01117   
01118   /* I thought SIGCHLD would just wake up the poll, but
01119    * that didn't seem to work, so added this pipe.
01120    * Probably the pipe is more likely to work on busted
01121    * operating systems anyhow.
01122    */
01123   if (pipe (sigchld_pipe) < 0)
01124     {
01125       _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
01126       exit (1);
01127     }
01128 
01129   babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
01130 
01131   _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
01132   
01133   write_pid (parent_pipe, grandchild_pid);
01134 
01135   check_babysit_events (grandchild_pid, parent_pipe, 0);
01136 
01137   while (TRUE)
01138     {
01139       DBusPollFD pfds[2];
01140       
01141       pfds[0].fd = parent_pipe;
01142       pfds[0].events = _DBUS_POLLIN;
01143       pfds[0].revents = 0;
01144 
01145       pfds[1].fd = sigchld_pipe[READ_END];
01146       pfds[1].events = _DBUS_POLLIN;
01147       pfds[1].revents = 0;
01148       
01149       if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
01150         {
01151           _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
01152           exit (1);
01153         }
01154 
01155       if (pfds[0].revents != 0)
01156         {
01157           check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
01158         }
01159       else if (pfds[1].revents & _DBUS_POLLIN)
01160         {
01161           char b;
01162           if (read (sigchld_pipe[READ_END], &b, 1) == -1)
01163             {
01164               /* ignore */
01165             }
01166           /* do waitpid check */
01167           check_babysit_events (grandchild_pid, parent_pipe, 0);
01168         }
01169     }
01170   
01171   exit (1);
01172 }
01173 
01193 dbus_bool_t
01194 _dbus_spawn_async_with_babysitter (DBusBabysitter          **sitter_p,
01195                                    const char               *log_name,
01196                                    char                    **argv,
01197                                    char                    **env,
01198                                    DBusSpawnChildSetupFunc   child_setup,
01199                                    void                     *user_data,
01200                                    DBusError                *error)
01201 {
01202   DBusBabysitter *sitter;
01203   int child_err_report_pipe[2] = { -1, -1 };
01204   int babysitter_pipe[2] = { -1, -1 };
01205   pid_t pid;
01206 #ifdef HAVE_SYSTEMD
01207   int fd_out = -1;
01208   int fd_err = -1;
01209 #endif
01210   
01211   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01212   _dbus_assert (argv[0] != NULL);
01213 
01214   if (sitter_p != NULL)
01215     *sitter_p = NULL;
01216 
01217   sitter = NULL;
01218 
01219   sitter = _dbus_babysitter_new ();
01220   if (sitter == NULL)
01221     {
01222       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01223       return FALSE;
01224     }
01225 
01226   sitter->log_name = _dbus_strdup (log_name);
01227   if (sitter->log_name == NULL && log_name != NULL)
01228     {
01229       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01230       goto cleanup_and_fail;
01231     }
01232 
01233   if (sitter->log_name == NULL)
01234     sitter->log_name = _dbus_strdup (argv[0]);
01235 
01236   if (sitter->log_name == NULL)
01237     {
01238       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01239       goto cleanup_and_fail;
01240     }
01241   
01242   if (!make_pipe (child_err_report_pipe, error))
01243     goto cleanup_and_fail;
01244 
01245   if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
01246     goto cleanup_and_fail;
01247 
01248   /* Setting up the babysitter is only useful in the parent,
01249    * but we don't want to run out of memory and fail
01250    * after we've already forked, since then we'd leak
01251    * child processes everywhere.
01252    */
01253   sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
01254                                          DBUS_WATCH_READABLE,
01255                                          TRUE, handle_watch, sitter, NULL);
01256   if (sitter->error_watch == NULL)
01257     {
01258       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01259       goto cleanup_and_fail;
01260     }
01261         
01262   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->error_watch))
01263     {
01264       /* we need to free it early so the destructor won't try to remove it
01265        * without it having been added, which DBusLoop doesn't allow */
01266       _dbus_watch_invalidate (sitter->error_watch);
01267       _dbus_watch_unref (sitter->error_watch);
01268       sitter->error_watch = NULL;
01269 
01270       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01271       goto cleanup_and_fail;
01272     }
01273       
01274   sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0],
01275                                           DBUS_WATCH_READABLE,
01276                                           TRUE, handle_watch, sitter, NULL);
01277   if (sitter->sitter_watch == NULL)
01278     {
01279       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01280       goto cleanup_and_fail;
01281     }
01282       
01283   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
01284     {
01285       /* we need to free it early so the destructor won't try to remove it
01286        * without it having been added, which DBusLoop doesn't allow */
01287       _dbus_watch_invalidate (sitter->sitter_watch);
01288       _dbus_watch_unref (sitter->sitter_watch);
01289       sitter->sitter_watch = NULL;
01290 
01291       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01292       goto cleanup_and_fail;
01293     }
01294 
01295   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01296 
01297 #ifdef HAVE_SYSTEMD
01298   /* This may fail, but it's not critical.
01299    * In particular, if we were compiled with journald support but are now
01300    * running on a non-systemd system, this is going to fail, so we
01301    * have to cope gracefully. */
01302   fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
01303   fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
01304 #endif
01305 
01306   pid = fork ();
01307   
01308   if (pid < 0)
01309     {
01310       dbus_set_error (error,
01311                       DBUS_ERROR_SPAWN_FORK_FAILED,
01312                       "Failed to fork (%s)",
01313                       _dbus_strerror (errno));
01314       goto cleanup_and_fail;
01315     }
01316   else if (pid == 0)
01317     {
01318       /* Immediate child, this is the babysitter process. */
01319       int grandchild_pid;
01320       
01321       /* Be sure we crash if the parent exits
01322        * and we write to the err_report_pipe
01323        */
01324       signal (SIGPIPE, SIG_DFL);
01325 
01326       /* Close the parent's end of the pipes. */
01327       close_and_invalidate (&child_err_report_pipe[READ_END]);
01328       close_and_invalidate (&babysitter_pipe[0]);
01329       
01330       /* Create the child that will exec () */
01331       grandchild_pid = fork ();
01332       
01333       if (grandchild_pid < 0)
01334         {
01335           write_err_and_exit (babysitter_pipe[1],
01336                               CHILD_FORK_FAILED);
01337           _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
01338         }
01339       else if (grandchild_pid == 0)
01340       {
01341           /* Go back to ignoring SIGPIPE, since it's evil
01342            */
01343           signal (SIGPIPE, SIG_IGN);
01344 
01345           close_and_invalidate (&babysitter_pipe[1]);
01346 #ifdef HAVE_SYSTEMD
01347           /* log to systemd journal if possible */
01348           if (fd_out >= 0)
01349             dup2 (fd_out, STDOUT_FILENO);
01350           if (fd_err >= 0)
01351             dup2 (fd_err, STDERR_FILENO);
01352           close_and_invalidate (&fd_out);
01353           close_and_invalidate (&fd_err);
01354 #endif
01355           do_exec (child_err_report_pipe[WRITE_END],
01356                    argv,
01357                    env,
01358                    child_setup, user_data);
01359           _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
01360         }
01361       else
01362         {
01363           close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01364 #ifdef HAVE_SYSTEMD
01365           close_and_invalidate (&fd_out);
01366           close_and_invalidate (&fd_err);
01367 #endif
01368           babysit (grandchild_pid, babysitter_pipe[1]);
01369           _dbus_assert_not_reached ("Got to code after babysit()");
01370         }
01371     }
01372   else
01373     {      
01374       /* Close the uncared-about ends of the pipes */
01375       close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01376       close_and_invalidate (&babysitter_pipe[1]);
01377 #ifdef HAVE_SYSTEMD
01378       close_and_invalidate (&fd_out);
01379       close_and_invalidate (&fd_err);
01380 #endif
01381 
01382       sitter->socket_to_babysitter = babysitter_pipe[0];
01383       babysitter_pipe[0] = -1;
01384       
01385       sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
01386       child_err_report_pipe[READ_END] = -1;
01387 
01388       sitter->sitter_pid = pid;
01389 
01390       if (sitter_p != NULL)
01391         *sitter_p = sitter;
01392       else
01393         _dbus_babysitter_unref (sitter);
01394 
01395       dbus_free_string_array (env);
01396 
01397       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01398       
01399       return TRUE;
01400     }
01401 
01402  cleanup_and_fail:
01403 
01404   _DBUS_ASSERT_ERROR_IS_SET (error);
01405   
01406   close_and_invalidate (&child_err_report_pipe[READ_END]);
01407   close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01408   close_and_invalidate (&babysitter_pipe[0]);
01409   close_and_invalidate (&babysitter_pipe[1]);
01410 #ifdef HAVE_SYSTEMD
01411   close_and_invalidate (&fd_out);
01412   close_and_invalidate (&fd_err);
01413 #endif
01414 
01415   if (sitter != NULL)
01416     _dbus_babysitter_unref (sitter);
01417   
01418   return FALSE;
01419 }
01420 
01421 void
01422 _dbus_babysitter_set_result_function  (DBusBabysitter             *sitter,
01423                                        DBusBabysitterFinishedFunc  finished,
01424                                        void                       *user_data)
01425 {
01426   sitter->finished_cb = finished;
01427   sitter->finished_data = user_data;
01428 }
01429 
01432 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01433 
01434 static char *
01435 get_test_exec (const char *exe,
01436                DBusString *scratch_space)
01437 {
01438   const char *dbus_test_exec;
01439 
01440   dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
01441 
01442   if (dbus_test_exec == NULL)
01443     dbus_test_exec = DBUS_TEST_EXEC;
01444 
01445   if (!_dbus_string_init (scratch_space))
01446     return NULL;
01447 
01448   if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
01449                                    dbus_test_exec, exe, DBUS_EXEEXT))
01450     {
01451       _dbus_string_free (scratch_space);
01452       return NULL;
01453     }
01454 
01455   return _dbus_string_get_data (scratch_space);
01456 }
01457 
01458 static void
01459 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
01460 {
01461   while (LIVE_CHILDREN (sitter))
01462     babysitter_iteration (sitter, TRUE);
01463 }
01464 
01465 static dbus_bool_t
01466 check_spawn_nonexistent (void *data)
01467 {
01468   char *argv[4] = { NULL, NULL, NULL, NULL };
01469   DBusBabysitter *sitter = NULL;
01470   DBusError error = DBUS_ERROR_INIT;
01471 
01472   /*** Test launching nonexistent binary */
01473   
01474   argv[0] = "/this/does/not/exist/32542sdgafgafdg";
01475   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv,
01476                                          NULL, NULL, NULL,
01477                                          &error))
01478     {
01479       _dbus_babysitter_block_for_child_exit (sitter);
01480       _dbus_babysitter_set_child_exit_error (sitter, &error);
01481     }
01482 
01483   if (sitter)
01484     _dbus_babysitter_unref (sitter);
01485 
01486   if (!dbus_error_is_set (&error))
01487     {
01488       _dbus_warn ("Did not get an error launching nonexistent executable\n");
01489       return FALSE;
01490     }
01491 
01492   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01493         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
01494     {
01495       _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
01496                   error.name, error.message);
01497       dbus_error_free (&error);
01498       return FALSE;
01499     }
01500 
01501   dbus_error_free (&error);
01502   
01503   return TRUE;
01504 }
01505 
01506 static dbus_bool_t
01507 check_spawn_segfault (void *data)
01508 {
01509   char *argv[4] = { NULL, NULL, NULL, NULL };
01510   DBusBabysitter *sitter = NULL;
01511   DBusError error = DBUS_ERROR_INIT;
01512   DBusString argv0;
01513 
01514   /*** Test launching segfault binary */
01515 
01516   argv[0] = get_test_exec ("test-segfault", &argv0);
01517 
01518   if (argv[0] == NULL)
01519     {
01520       /* OOM was simulated, never mind */
01521       return TRUE;
01522     }
01523 
01524   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
01525                                          NULL, NULL, NULL,
01526                                          &error))
01527     {
01528       _dbus_babysitter_block_for_child_exit (sitter);
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 launching segfaulting 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 launching segfaulting 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 static dbus_bool_t
01558 check_spawn_exit (void *data)
01559 {
01560   char *argv[4] = { NULL, NULL, NULL, NULL };
01561   DBusBabysitter *sitter = NULL;
01562   DBusError error = DBUS_ERROR_INIT;
01563   DBusString argv0;
01564 
01565   /*** Test launching exit failure binary */
01566 
01567   argv[0] = get_test_exec ("test-exit", &argv0);
01568 
01569   if (argv[0] == NULL)
01570     {
01571       /* OOM was simulated, never mind */
01572       return TRUE;
01573     }
01574 
01575   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
01576                                          NULL, NULL, NULL,
01577                                          &error))
01578     {
01579       _dbus_babysitter_block_for_child_exit (sitter);
01580       _dbus_babysitter_set_child_exit_error (sitter, &error);
01581     }
01582 
01583   _dbus_string_free (&argv0);
01584 
01585   if (sitter)
01586     _dbus_babysitter_unref (sitter);
01587 
01588   if (!dbus_error_is_set (&error))
01589     {
01590       _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
01591       return FALSE;
01592     }
01593 
01594   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01595         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
01596     {
01597       _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
01598                   error.name, error.message);
01599       dbus_error_free (&error);
01600       return FALSE;
01601     }
01602 
01603   dbus_error_free (&error);
01604   
01605   return TRUE;
01606 }
01607 
01608 static dbus_bool_t
01609 check_spawn_and_kill (void *data)
01610 {
01611   char *argv[4] = { NULL, NULL, NULL, NULL };
01612   DBusBabysitter *sitter = NULL;
01613   DBusError error = DBUS_ERROR_INIT;
01614   DBusString argv0;
01615 
01616   /*** Test launching sleeping binary then killing it */
01617 
01618   argv[0] = get_test_exec ("test-sleep-forever", &argv0);
01619 
01620   if (argv[0] == NULL)
01621     {
01622       /* OOM was simulated, never mind */
01623       return TRUE;
01624     }
01625 
01626   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
01627                                          NULL, NULL, NULL,
01628                                          &error))
01629     {
01630       _dbus_babysitter_kill_child (sitter);
01631       
01632       _dbus_babysitter_block_for_child_exit (sitter);
01633       
01634       _dbus_babysitter_set_child_exit_error (sitter, &error);
01635     }
01636 
01637   _dbus_string_free (&argv0);
01638 
01639   if (sitter)
01640     _dbus_babysitter_unref (sitter);
01641 
01642   if (!dbus_error_is_set (&error))
01643     {
01644       _dbus_warn ("Did not get an error after killing spawned binary\n");
01645       return FALSE;
01646     }
01647 
01648   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01649         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01650     {
01651       _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
01652                   error.name, error.message);
01653       dbus_error_free (&error);
01654       return FALSE;
01655     }
01656 
01657   dbus_error_free (&error);
01658   
01659   return TRUE;
01660 }
01661 
01662 dbus_bool_t
01663 _dbus_spawn_test (const char *test_data_dir)
01664 {
01665   if (!_dbus_test_oom_handling ("spawn_nonexistent",
01666                                 check_spawn_nonexistent,
01667                                 NULL))
01668     return FALSE;
01669 
01670   if (!_dbus_test_oom_handling ("spawn_segfault",
01671                                 check_spawn_segfault,
01672                                 NULL))
01673     return FALSE;
01674 
01675   if (!_dbus_test_oom_handling ("spawn_exit",
01676                                 check_spawn_exit,
01677                                 NULL))
01678     return FALSE;
01679 
01680   if (!_dbus_test_oom_handling ("spawn_and_kill",
01681                                 check_spawn_and_kill,
01682                                 NULL))
01683     return FALSE;
01684   
01685   return TRUE;
01686 }
01687 #endif