D-Bus  1.10.12
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   DBusSocket socket_to_babysitter; 
00247   int error_pipe_from_child; 
00249   pid_t sitter_pid;  
00250   pid_t grandchild_pid; 
00252   DBusWatchList *watches; 
00254   DBusWatch *error_watch; 
00255   DBusWatch *sitter_watch; 
00257   DBusBabysitterFinishedFunc finished_cb;
00258   void *finished_data;
00259 
00260   int errnum; 
00261   int status; 
00262   unsigned int have_child_status : 1; 
00263   unsigned int have_fork_errnum : 1; 
00264   unsigned int have_exec_errnum : 1; 
00265 };
00266 
00267 static DBusBabysitter*
00268 _dbus_babysitter_new (void)
00269 {
00270   DBusBabysitter *sitter;
00271 
00272   sitter = dbus_new0 (DBusBabysitter, 1);
00273   if (sitter == NULL)
00274     return NULL;
00275 
00276   sitter->refcount = 1;
00277 
00278   sitter->socket_to_babysitter.fd = -1;
00279   sitter->error_pipe_from_child = -1;
00280   
00281   sitter->sitter_pid = -1;
00282   sitter->grandchild_pid = -1;
00283 
00284   sitter->watches = _dbus_watch_list_new ();
00285   if (sitter->watches == NULL)
00286     goto failed;
00287   
00288   return sitter;
00289 
00290  failed:
00291   _dbus_babysitter_unref (sitter);
00292   return NULL;
00293 }
00294 
00301 DBusBabysitter *
00302 _dbus_babysitter_ref (DBusBabysitter *sitter)
00303 {
00304   _dbus_assert (sitter != NULL);
00305   _dbus_assert (sitter->refcount > 0);
00306   
00307   sitter->refcount += 1;
00308 
00309   return sitter;
00310 }
00311 
00312 static void close_socket_to_babysitter  (DBusBabysitter *sitter);
00313 static void close_error_pipe_from_child (DBusBabysitter *sitter);
00314 
00323 void
00324 _dbus_babysitter_unref (DBusBabysitter *sitter)
00325 {
00326   _dbus_assert (sitter != NULL);
00327   _dbus_assert (sitter->refcount > 0);
00328   
00329   sitter->refcount -= 1;
00330   if (sitter->refcount == 0)
00331     {
00332       /* 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                     /* Do not reset sitter->errnum to 0 here. We get here if
00458                      * the babysitter reports that the grandchild process has
00459                      * exited, and there are two ways that can happen:
00460                      *
00461                      * 1. grandchild successfully exec()s the desired process,
00462                      * but then the desired process exits or is terminated
00463                      * by a signal. The babysitter observes this and reports
00464                      * CHILD_EXITED.
00465                      *
00466                      * 2. grandchild fails to exec() the desired process,
00467                      * attempts to report the exec() failure (which
00468                      * we will receive as CHILD_EXEC_FAILED), and then
00469                      * exits itself (which will prompt the babysitter to
00470                      * send CHILD_EXITED). We want the CHILD_EXEC_FAILED
00471                      * to take precedence (and have its errno logged),
00472                      * which _dbus_babysitter_set_child_exit_error() does.
00473                      */
00474                     sitter->have_child_status = TRUE;
00475                     sitter->status = arg;
00476                     _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
00477                                    WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
00478                                    WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
00479                   }
00480                 else if (what == CHILD_FORK_FAILED)
00481                   {
00482                     sitter->have_fork_errnum = TRUE;
00483                     sitter->errnum = arg;
00484                     _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
00485                   }
00486                 else if (what == CHILD_EXEC_FAILED)
00487                   {
00488                     sitter->have_exec_errnum = TRUE;
00489                     sitter->errnum = arg;
00490                     _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
00491                   }
00492               }
00493           }
00494           break;
00495         case CHILD_PID:
00496           {
00497             pid_t pid = -1;
00498 
00499             r = read_pid (fd, &pid, &error);
00500             
00501             switch (r)
00502               {
00503               case READ_STATUS_ERROR:
00504                 _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
00505                 dbus_error_free (&error);
00506                 return r;
00507               case READ_STATUS_EOF:
00508                 return r;
00509               case READ_STATUS_OK:
00510                 break;
00511               }
00512             
00513             sitter->grandchild_pid = pid;
00514             
00515             _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
00516           }
00517           break;
00518         default:
00519           _dbus_warn ("Unknown message received from babysitter process\n");
00520           break;
00521         }
00522     }
00523 
00524   return r;
00525 }
00526 
00527 static void
00528 close_socket_to_babysitter (DBusBabysitter *sitter)
00529 {
00530   _dbus_verbose ("Closing babysitter\n");
00531 
00532   if (sitter->sitter_watch != NULL)
00533     {
00534       _dbus_assert (sitter->watches != NULL);
00535       _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
00536       _dbus_watch_invalidate (sitter->sitter_watch);
00537       _dbus_watch_unref (sitter->sitter_watch);
00538       sitter->sitter_watch = NULL;
00539     }
00540 
00541   if (sitter->socket_to_babysitter.fd >= 0)
00542     {
00543       _dbus_close_socket (sitter->socket_to_babysitter, NULL);
00544       sitter->socket_to_babysitter.fd = -1;
00545     }
00546 }
00547 
00548 static void
00549 close_error_pipe_from_child (DBusBabysitter *sitter)
00550 {
00551   _dbus_verbose ("Closing child error\n");
00552 
00553   if (sitter->error_watch != NULL)
00554     {
00555       _dbus_assert (sitter->watches != NULL);
00556       _dbus_watch_list_remove_watch (sitter->watches,  sitter->error_watch);
00557       _dbus_watch_invalidate (sitter->error_watch);
00558       _dbus_watch_unref (sitter->error_watch);
00559       sitter->error_watch = NULL;
00560     }
00561 
00562   if (sitter->error_pipe_from_child >= 0)
00563     {
00564       _dbus_close (sitter->error_pipe_from_child, NULL);
00565       sitter->error_pipe_from_child = -1;
00566     }
00567 }
00568 
00569 static void
00570 handle_babysitter_socket (DBusBabysitter *sitter,
00571                           int             revents)
00572 {
00573   /* Even if we have POLLHUP, we want to keep reading
00574    * data until POLLIN goes away; so this function only
00575    * looks at HUP/ERR if no IN is set.
00576    */
00577   if (revents & _DBUS_POLLIN)
00578     {
00579       _dbus_verbose ("Reading data from babysitter\n");
00580       if (read_data (sitter, sitter->socket_to_babysitter.fd) != READ_STATUS_OK)
00581         close_socket_to_babysitter (sitter);
00582     }
00583   else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00584     {
00585       close_socket_to_babysitter (sitter);
00586     }
00587 }
00588 
00589 static void
00590 handle_error_pipe (DBusBabysitter *sitter,
00591                    int             revents)
00592 {
00593   if (revents & _DBUS_POLLIN)
00594     {
00595       _dbus_verbose ("Reading data from child error\n");
00596       if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
00597         close_error_pipe_from_child (sitter);
00598     }
00599   else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
00600     {
00601       close_error_pipe_from_child (sitter);
00602     }
00603 }
00604 
00605 /* returns whether there were any poll events handled */
00606 static dbus_bool_t
00607 babysitter_iteration (DBusBabysitter *sitter,
00608                       dbus_bool_t     block)
00609 {
00610   DBusPollFD fds[2];
00611   int i;
00612   dbus_bool_t descriptors_ready;
00613 
00614   descriptors_ready = FALSE;
00615   
00616   i = 0;
00617 
00618   if (sitter->error_pipe_from_child >= 0)
00619     {
00620       fds[i].fd = sitter->error_pipe_from_child;
00621       fds[i].events = _DBUS_POLLIN;
00622       fds[i].revents = 0;
00623       ++i;
00624     }
00625   
00626   if (sitter->socket_to_babysitter.fd >= 0)
00627     {
00628       fds[i].fd = sitter->socket_to_babysitter.fd;
00629       fds[i].events = _DBUS_POLLIN;
00630       fds[i].revents = 0;
00631       ++i;
00632     }
00633 
00634   if (i > 0)
00635     {
00636       int ret;
00637 
00638       do
00639         {
00640           ret = _dbus_poll (fds, i, 0);
00641         }
00642       while (ret < 0 && errno == EINTR);
00643 
00644       if (ret == 0 && block)
00645         {
00646           do
00647             {
00648               ret = _dbus_poll (fds, i, -1);
00649             }
00650           while (ret < 0 && errno == EINTR);
00651         }
00652 
00653       if (ret > 0)
00654         {
00655           descriptors_ready = TRUE;
00656           
00657           while (i > 0)
00658             {
00659               --i;
00660               if (fds[i].fd == sitter->error_pipe_from_child)
00661                 handle_error_pipe (sitter, fds[i].revents);
00662               else if (fds[i].fd == sitter->socket_to_babysitter.fd)
00663                 handle_babysitter_socket (sitter, fds[i].revents);
00664             }
00665         }
00666     }
00667 
00668   return descriptors_ready;
00669 }
00670 
00675 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter.fd >= 0 || (sitter)->error_pipe_from_child >= 0)
00676 
00683 void
00684 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
00685 {
00686   /* be sure we have the PID of the child */
00687   while (LIVE_CHILDREN (sitter) &&
00688          sitter->grandchild_pid == -1)
00689     babysitter_iteration (sitter, TRUE);
00690 
00691   _dbus_verbose ("Got child PID %ld for killing\n",
00692                  (long) sitter->grandchild_pid);
00693   
00694   if (sitter->grandchild_pid == -1)
00695     return; /* child is already dead, or we're so hosed we'll never recover */
00696 
00697   kill (sitter->grandchild_pid, SIGKILL);
00698 }
00699 
00705 dbus_bool_t
00706 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
00707 {
00708 
00709   /* Be sure we're up-to-date */
00710   while (LIVE_CHILDREN (sitter) &&
00711          babysitter_iteration (sitter, FALSE))
00712     ;
00713 
00714   /* We will have exited the babysitter when the child has exited */
00715   return sitter->socket_to_babysitter.fd < 0;
00716 }
00717 
00730 dbus_bool_t
00731 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
00732                                         int            *status)
00733 {
00734   if (!_dbus_babysitter_get_child_exited (sitter))
00735     _dbus_assert_not_reached ("Child has not exited");
00736   
00737   if (!sitter->have_child_status ||
00738       !(WIFEXITED (sitter->status)))
00739     return FALSE;
00740 
00741   *status = WEXITSTATUS (sitter->status);
00742   return TRUE;
00743 }
00744 
00754 void
00755 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
00756                                        DBusError      *error)
00757 {
00758   if (!_dbus_babysitter_get_child_exited (sitter))
00759     return;
00760 
00761   /* Note that if exec fails, we will also get a child status
00762    * from the babysitter saying the child exited,
00763    * so we need to give priority to the exec error
00764    */
00765   if (sitter->have_exec_errnum)
00766     {
00767       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
00768                       "Failed to execute program %s: %s",
00769                       sitter->log_name, _dbus_strerror (sitter->errnum));
00770     }
00771   else if (sitter->have_fork_errnum)
00772     {
00773       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00774                       "Failed to fork a new process %s: %s",
00775                       sitter->log_name, _dbus_strerror (sitter->errnum));
00776     }
00777   else if (sitter->have_child_status)
00778     {
00779       if (WIFEXITED (sitter->status))
00780         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
00781                         "Process %s exited with status %d",
00782                         sitter->log_name, WEXITSTATUS (sitter->status));
00783       else if (WIFSIGNALED (sitter->status))
00784         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
00785                         "Process %s received signal %d",
00786                         sitter->log_name, WTERMSIG (sitter->status));
00787       else
00788         dbus_set_error (error, DBUS_ERROR_FAILED,
00789                         "Process %s exited abnormally",
00790                         sitter->log_name);
00791     }
00792   else
00793     {
00794       dbus_set_error (error, DBUS_ERROR_FAILED,
00795                       "Process %s exited, reason unknown",
00796                       sitter->log_name);
00797     }
00798 }
00799 
00812 dbus_bool_t
00813 _dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
00814                                       DBusAddWatchFunction       add_function,
00815                                       DBusRemoveWatchFunction    remove_function,
00816                                       DBusWatchToggledFunction   toggled_function,
00817                                       void                      *data,
00818                                       DBusFreeFunction           free_data_function)
00819 {
00820   return _dbus_watch_list_set_functions (sitter->watches,
00821                                          add_function,
00822                                          remove_function,
00823                                          toggled_function,
00824                                          data,
00825                                          free_data_function);
00826 }
00827 
00828 static dbus_bool_t
00829 handle_watch (DBusWatch       *watch,
00830               unsigned int     condition,
00831               void            *data)
00832 {
00833   DBusBabysitter *sitter = _dbus_babysitter_ref (data);
00834   int revents;
00835   int fd;
00836   
00837   revents = 0;
00838   if (condition & DBUS_WATCH_READABLE)
00839     revents |= _DBUS_POLLIN;
00840   if (condition & DBUS_WATCH_ERROR)
00841     revents |= _DBUS_POLLERR;
00842   if (condition & DBUS_WATCH_HANGUP)
00843     revents |= _DBUS_POLLHUP;
00844 
00845   fd = dbus_watch_get_socket (watch);
00846 
00847   if (fd == sitter->error_pipe_from_child)
00848     handle_error_pipe (sitter, revents);
00849   else if (fd == sitter->socket_to_babysitter.fd)
00850     handle_babysitter_socket (sitter, revents);
00851 
00852   while (LIVE_CHILDREN (sitter) &&
00853          babysitter_iteration (sitter, FALSE))
00854     ;
00855 
00856   /* fd.o #32992: if the handle_* methods closed their sockets, they previously
00857    * didn't always remove the watches. Check that we don't regress. */
00858   _dbus_assert (sitter->socket_to_babysitter.fd != -1 || sitter->sitter_watch == NULL);
00859   _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
00860 
00861   if (_dbus_babysitter_get_child_exited (sitter) &&
00862       sitter->finished_cb != NULL)
00863     {
00864       sitter->finished_cb (sitter, sitter->finished_data);
00865       sitter->finished_cb = NULL;
00866     }
00867 
00868   _dbus_babysitter_unref (sitter);
00869   return TRUE;
00870 }
00871 
00873 #define READ_END 0
00874 
00875 #define WRITE_END 1
00876 
00877 
00878 /* Avoids a danger in re-entrant situations (calling close()
00879  * on a file descriptor twice, and another module has
00880  * re-opened it since the first close).
00881  *
00882  * This previously claimed to be relevant for threaded situations, but by
00883  * trivial inspection, it is not thread-safe. It doesn't actually
00884  * matter, since this module is only used in the -util variant of the
00885  * library, which is only used in single-threaded situations.
00886  */
00887 static int
00888 close_and_invalidate (int *fd)
00889 {
00890   int ret;
00891 
00892   if (*fd < 0)
00893     return -1;
00894   else
00895     {
00896       ret = _dbus_close (*fd, NULL);
00897       *fd = -1;
00898     }
00899 
00900   return ret;
00901 }
00902 
00903 static dbus_bool_t
00904 make_pipe (int         p[2],
00905            DBusError  *error)
00906 {
00907   int retval;
00908 
00909 #ifdef HAVE_PIPE2
00910   dbus_bool_t cloexec_done;
00911 
00912   retval = pipe2 (p, O_CLOEXEC);
00913   cloexec_done = retval >= 0;
00914 
00915   /* Check if kernel seems to be too old to know pipe2(). We assume
00916      that if pipe2 is available, O_CLOEXEC is too.  */
00917   if (retval < 0 && errno == ENOSYS)
00918 #endif
00919     {
00920       retval = pipe(p);
00921     }
00922 
00923   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00924 
00925   if (retval < 0)
00926     {
00927       dbus_set_error (error,
00928                       DBUS_ERROR_SPAWN_FAILED,
00929                       "Failed to create pipe for communicating with child process (%s)",
00930                       _dbus_strerror (errno));
00931       return FALSE;
00932     }
00933 
00934 #ifdef HAVE_PIPE2
00935   if (!cloexec_done)
00936 #endif
00937     {
00938       _dbus_fd_set_close_on_exec (p[0]);
00939       _dbus_fd_set_close_on_exec (p[1]);
00940     }
00941 
00942   return TRUE;
00943 }
00944 
00945 static void
00946 do_write (int fd, const void *buf, size_t count)
00947 {
00948   size_t bytes_written;
00949   int ret;
00950   
00951   bytes_written = 0;
00952   
00953  again:
00954   
00955   ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
00956 
00957   if (ret < 0)
00958     {
00959       if (errno == EINTR)
00960         goto again;
00961       else
00962         {
00963           _dbus_warn ("Failed to write data to pipe!\n");
00964           exit (1); /* give up, we suck */
00965         }
00966     }
00967   else
00968     bytes_written += ret;
00969   
00970   if (bytes_written < count)
00971     goto again;
00972 }
00973 
00974 static void
00975 write_err_and_exit (int fd, int msg)
00976 {
00977   int en = errno;
00978 
00979   do_write (fd, &msg, sizeof (msg));
00980   do_write (fd, &en, sizeof (en));
00981   
00982   exit (1);
00983 }
00984 
00985 static void
00986 write_pid (int fd, pid_t pid)
00987 {
00988   int msg = CHILD_PID;
00989   
00990   do_write (fd, &msg, sizeof (msg));
00991   do_write (fd, &pid, sizeof (pid));
00992 }
00993 
00994 static void
00995 write_status_and_exit (int fd, int status)
00996 {
00997   int msg = CHILD_EXITED;
00998   
00999   do_write (fd, &msg, sizeof (msg));
01000   do_write (fd, &status, sizeof (status));
01001   
01002   exit (0);
01003 }
01004 
01005 static void
01006 do_exec (int                       child_err_report_fd,
01007          char                    **argv,
01008          char                    **envp,
01009          DBusSpawnChildSetupFunc   child_setup,
01010          void                     *user_data)
01011 {
01012 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01013   int i, max_open;
01014 #endif
01015 
01016   _dbus_verbose_reset ();
01017   _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
01018                  _dbus_getpid ());
01019   
01020   if (child_setup)
01021     (* child_setup) (user_data);
01022 
01023 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01024   max_open = sysconf (_SC_OPEN_MAX);
01025   
01026   for (i = 3; i < max_open; i++)
01027     {
01028       int retval;
01029 
01030       if (i == child_err_report_fd)
01031         continue;
01032       
01033       retval = fcntl (i, F_GETFD);
01034 
01035       if (retval != -1 && !(retval & FD_CLOEXEC))
01036         _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
01037     }
01038 #endif
01039 
01040   if (envp == NULL)
01041     {
01042       _dbus_assert (environ != NULL);
01043 
01044       envp = environ;
01045     }
01046   
01047   execve (argv[0], argv, envp);
01048   
01049   /* Exec failed */
01050   write_err_and_exit (child_err_report_fd,
01051                       CHILD_EXEC_FAILED);
01052 }
01053 
01054 static void
01055 check_babysit_events (pid_t grandchild_pid,
01056                       int   parent_pipe,
01057                       int   revents)
01058 {
01059   pid_t ret;
01060   int status;
01061   
01062   do
01063     {
01064       ret = waitpid (grandchild_pid, &status, WNOHANG);
01065       /* The man page says EINTR can't happen with WNOHANG,
01066        * but there are reports of it (maybe only with valgrind?)
01067        */
01068     }
01069   while (ret < 0 && errno == EINTR);
01070 
01071   if (ret == 0)
01072     {
01073       _dbus_verbose ("no child exited\n");
01074       
01075       ; /* no child exited */
01076     }
01077   else if (ret < 0)
01078     {
01079       /* This isn't supposed to happen. */
01080       _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
01081                   _dbus_strerror (errno));
01082       exit (1);
01083     }
01084   else if (ret == grandchild_pid)
01085     {
01086       /* Child exited */
01087       _dbus_verbose ("reaped child pid %ld\n", (long) ret);
01088       
01089       write_status_and_exit (parent_pipe, status);
01090     }
01091   else
01092     {
01093       _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
01094                   (int) ret);
01095       exit (1);
01096     }
01097 
01098   if (revents & _DBUS_POLLIN)
01099     {
01100       _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
01101     }
01102 
01103   if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
01104     {
01105       /* Parent is gone, so we just exit */
01106       _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
01107       exit (0);
01108     }
01109 }
01110 
01111 static int babysit_sigchld_pipe = -1;
01112 
01113 static void
01114 babysit_signal_handler (int signo)
01115 {
01116   char b = '\0';
01117  again:
01118   if (write (babysit_sigchld_pipe, &b, 1) <= 0) 
01119     if (errno == EINTR)
01120       goto again;
01121 }
01122 
01123 static void
01124 babysit (pid_t grandchild_pid,
01125          int   parent_pipe)
01126 {
01127   int sigchld_pipe[2];
01128 
01129   /* We don't exec, so we keep parent state, such as the pid that
01130    * _dbus_verbose() uses. Reset the pid here.
01131    */
01132   _dbus_verbose_reset ();
01133   
01134   /* I thought SIGCHLD would just wake up the poll, but
01135    * that didn't seem to work, so added this pipe.
01136    * Probably the pipe is more likely to work on busted
01137    * operating systems anyhow.
01138    */
01139   if (pipe (sigchld_pipe) < 0)
01140     {
01141       _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
01142       exit (1);
01143     }
01144 
01145   babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
01146 
01147   _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
01148   
01149   write_pid (parent_pipe, grandchild_pid);
01150 
01151   check_babysit_events (grandchild_pid, parent_pipe, 0);
01152 
01153   while (TRUE)
01154     {
01155       DBusPollFD pfds[2];
01156       
01157       pfds[0].fd = parent_pipe;
01158       pfds[0].events = _DBUS_POLLIN;
01159       pfds[0].revents = 0;
01160 
01161       pfds[1].fd = sigchld_pipe[READ_END];
01162       pfds[1].events = _DBUS_POLLIN;
01163       pfds[1].revents = 0;
01164       
01165       if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
01166         {
01167           _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
01168           exit (1);
01169         }
01170 
01171       if (pfds[0].revents != 0)
01172         {
01173           check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
01174         }
01175       else if (pfds[1].revents & _DBUS_POLLIN)
01176         {
01177           char b;
01178           if (read (sigchld_pipe[READ_END], &b, 1) == -1)
01179             {
01180               /* ignore */
01181             }
01182           /* do waitpid check */
01183           check_babysit_events (grandchild_pid, parent_pipe, 0);
01184         }
01185     }
01186   
01187   exit (1);
01188 }
01189 
01209 dbus_bool_t
01210 _dbus_spawn_async_with_babysitter (DBusBabysitter          **sitter_p,
01211                                    const char               *log_name,
01212                                    char                    **argv,
01213                                    char                    **env,
01214                                    DBusSpawnChildSetupFunc   child_setup,
01215                                    void                     *user_data,
01216                                    DBusError                *error)
01217 {
01218   DBusBabysitter *sitter;
01219   int child_err_report_pipe[2] = { -1, -1 };
01220   DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT };
01221   pid_t pid;
01222 #ifdef HAVE_SYSTEMD
01223   int fd_out = -1;
01224   int fd_err = -1;
01225 #endif
01226   
01227   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01228   _dbus_assert (argv[0] != NULL);
01229 
01230   if (sitter_p != NULL)
01231     *sitter_p = NULL;
01232 
01233   sitter = NULL;
01234 
01235   sitter = _dbus_babysitter_new ();
01236   if (sitter == NULL)
01237     {
01238       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01239       return FALSE;
01240     }
01241 
01242   sitter->log_name = _dbus_strdup (log_name);
01243   if (sitter->log_name == NULL && log_name != NULL)
01244     {
01245       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01246       goto cleanup_and_fail;
01247     }
01248 
01249   if (sitter->log_name == NULL)
01250     sitter->log_name = _dbus_strdup (argv[0]);
01251 
01252   if (sitter->log_name == NULL)
01253     {
01254       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01255       goto cleanup_and_fail;
01256     }
01257   
01258   if (!make_pipe (child_err_report_pipe, error))
01259     goto cleanup_and_fail;
01260 
01261   if (!_dbus_socketpair (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
01262     goto cleanup_and_fail;
01263 
01264   /* Setting up the babysitter is only useful in the parent,
01265    * but we don't want to run out of memory and fail
01266    * after we've already forked, since then we'd leak
01267    * child processes everywhere.
01268    */
01269   sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
01270                                          DBUS_WATCH_READABLE,
01271                                          TRUE, handle_watch, sitter, NULL);
01272   if (sitter->error_watch == NULL)
01273     {
01274       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01275       goto cleanup_and_fail;
01276     }
01277         
01278   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->error_watch))
01279     {
01280       /* we need to free it early so the destructor won't try to remove it
01281        * without it having been added, which DBusLoop doesn't allow */
01282       _dbus_watch_invalidate (sitter->error_watch);
01283       _dbus_watch_unref (sitter->error_watch);
01284       sitter->error_watch = NULL;
01285 
01286       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01287       goto cleanup_and_fail;
01288     }
01289       
01290   sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0].fd,
01291                                           DBUS_WATCH_READABLE,
01292                                           TRUE, handle_watch, sitter, NULL);
01293   if (sitter->sitter_watch == NULL)
01294     {
01295       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01296       goto cleanup_and_fail;
01297     }
01298       
01299   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
01300     {
01301       /* we need to free it early so the destructor won't try to remove it
01302        * without it having been added, which DBusLoop doesn't allow */
01303       _dbus_watch_invalidate (sitter->sitter_watch);
01304       _dbus_watch_unref (sitter->sitter_watch);
01305       sitter->sitter_watch = NULL;
01306 
01307       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01308       goto cleanup_and_fail;
01309     }
01310 
01311   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01312 
01313 #ifdef HAVE_SYSTEMD
01314   /* This may fail, but it's not critical.
01315    * In particular, if we were compiled with journald support but are now
01316    * running on a non-systemd system, this is going to fail, so we
01317    * have to cope gracefully. */
01318   fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
01319   fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
01320 #endif
01321 
01322   pid = fork ();
01323   
01324   if (pid < 0)
01325     {
01326       dbus_set_error (error,
01327                       DBUS_ERROR_SPAWN_FORK_FAILED,
01328                       "Failed to fork (%s)",
01329                       _dbus_strerror (errno));
01330       goto cleanup_and_fail;
01331     }
01332   else if (pid == 0)
01333     {
01334       /* Immediate child, this is the babysitter process. */
01335       int grandchild_pid;
01336       
01337       /* Be sure we crash if the parent exits
01338        * and we write to the err_report_pipe
01339        */
01340       signal (SIGPIPE, SIG_DFL);
01341 
01342       /* Close the parent's end of the pipes. */
01343       close_and_invalidate (&child_err_report_pipe[READ_END]);
01344       close_and_invalidate (&babysitter_pipe[0].fd);
01345       
01346       /* Create the child that will exec () */
01347       grandchild_pid = fork ();
01348       
01349       if (grandchild_pid < 0)
01350         {
01351           write_err_and_exit (babysitter_pipe[1].fd,
01352                               CHILD_FORK_FAILED);
01353           _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
01354         }
01355       else if (grandchild_pid == 0)
01356       {
01357 #ifdef __linux__
01358           int fd = -1;
01359 
01360 #ifdef O_CLOEXEC
01361           fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
01362 #endif
01363 
01364           if (fd < 0)
01365             {
01366               fd = open ("/proc/self/oom_score_adj", O_WRONLY);
01367               _dbus_fd_set_close_on_exec (fd);
01368             }
01369 
01370           if (fd >= 0)
01371             {
01372               if (write (fd, "0", sizeof (char)) < 0)
01373                 _dbus_warn ("writing oom_score_adj error: %s\n", strerror (errno));
01374               _dbus_close (fd, NULL);
01375             }
01376 #endif
01377           /* Go back to ignoring SIGPIPE, since it's evil
01378            */
01379           signal (SIGPIPE, SIG_IGN);
01380 
01381           close_and_invalidate (&babysitter_pipe[1].fd);
01382 #ifdef HAVE_SYSTEMD
01383           /* log to systemd journal if possible */
01384           if (fd_out >= 0)
01385             dup2 (fd_out, STDOUT_FILENO);
01386           if (fd_err >= 0)
01387             dup2 (fd_err, STDERR_FILENO);
01388           close_and_invalidate (&fd_out);
01389           close_and_invalidate (&fd_err);
01390 #endif
01391           do_exec (child_err_report_pipe[WRITE_END],
01392                    argv,
01393                    env,
01394                    child_setup, user_data);
01395           _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
01396         }
01397       else
01398         {
01399           close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01400 #ifdef HAVE_SYSTEMD
01401           close_and_invalidate (&fd_out);
01402           close_and_invalidate (&fd_err);
01403 #endif
01404           babysit (grandchild_pid, babysitter_pipe[1].fd);
01405           _dbus_assert_not_reached ("Got to code after babysit()");
01406         }
01407     }
01408   else
01409     {      
01410       /* Close the uncared-about ends of the pipes */
01411       close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01412       close_and_invalidate (&babysitter_pipe[1].fd);
01413 #ifdef HAVE_SYSTEMD
01414       close_and_invalidate (&fd_out);
01415       close_and_invalidate (&fd_err);
01416 #endif
01417 
01418       sitter->socket_to_babysitter = babysitter_pipe[0];
01419       babysitter_pipe[0].fd = -1;
01420       
01421       sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
01422       child_err_report_pipe[READ_END] = -1;
01423 
01424       sitter->sitter_pid = pid;
01425 
01426       if (sitter_p != NULL)
01427         *sitter_p = sitter;
01428       else
01429         _dbus_babysitter_unref (sitter);
01430 
01431       dbus_free_string_array (env);
01432 
01433       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01434       
01435       return TRUE;
01436     }
01437 
01438  cleanup_and_fail:
01439 
01440   _DBUS_ASSERT_ERROR_IS_SET (error);
01441   
01442   close_and_invalidate (&child_err_report_pipe[READ_END]);
01443   close_and_invalidate (&child_err_report_pipe[WRITE_END]);
01444   close_and_invalidate (&babysitter_pipe[0].fd);
01445   close_and_invalidate (&babysitter_pipe[1].fd);
01446 #ifdef HAVE_SYSTEMD
01447   close_and_invalidate (&fd_out);
01448   close_and_invalidate (&fd_err);
01449 #endif
01450 
01451   if (sitter != NULL)
01452     _dbus_babysitter_unref (sitter);
01453   
01454   return FALSE;
01455 }
01456 
01457 void
01458 _dbus_babysitter_set_result_function  (DBusBabysitter             *sitter,
01459                                        DBusBabysitterFinishedFunc  finished,
01460                                        void                       *user_data)
01461 {
01462   sitter->finished_cb = finished;
01463   sitter->finished_data = user_data;
01464 }
01465 
01468 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01469 
01470 static char *
01471 get_test_exec (const char *exe,
01472                DBusString *scratch_space)
01473 {
01474   const char *dbus_test_exec;
01475 
01476   dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
01477 
01478   if (dbus_test_exec == NULL)
01479     dbus_test_exec = DBUS_TEST_EXEC;
01480 
01481   if (!_dbus_string_init (scratch_space))
01482     return NULL;
01483 
01484   if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
01485                                    dbus_test_exec, exe, DBUS_EXEEXT))
01486     {
01487       _dbus_string_free (scratch_space);
01488       return NULL;
01489     }
01490 
01491   return _dbus_string_get_data (scratch_space);
01492 }
01493 
01494 static void
01495 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
01496 {
01497   while (LIVE_CHILDREN (sitter))
01498     babysitter_iteration (sitter, TRUE);
01499 }
01500 
01501 static dbus_bool_t
01502 check_spawn_nonexistent (void *data)
01503 {
01504   char *argv[4] = { NULL, NULL, NULL, NULL };
01505   DBusBabysitter *sitter = NULL;
01506   DBusError error = DBUS_ERROR_INIT;
01507 
01508   /*** Test launching nonexistent binary */
01509   
01510   argv[0] = "/this/does/not/exist/32542sdgafgafdg";
01511   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv,
01512                                          NULL, NULL, NULL,
01513                                          &error))
01514     {
01515       _dbus_babysitter_block_for_child_exit (sitter);
01516       _dbus_babysitter_set_child_exit_error (sitter, &error);
01517     }
01518 
01519   if (sitter)
01520     _dbus_babysitter_unref (sitter);
01521 
01522   if (!dbus_error_is_set (&error))
01523     {
01524       _dbus_warn ("Did not get an error launching nonexistent executable\n");
01525       return FALSE;
01526     }
01527 
01528   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01529         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
01530     {
01531       _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
01532                   error.name, error.message);
01533       dbus_error_free (&error);
01534       return FALSE;
01535     }
01536 
01537   dbus_error_free (&error);
01538   
01539   return TRUE;
01540 }
01541 
01542 static dbus_bool_t
01543 check_spawn_segfault (void *data)
01544 {
01545   char *argv[4] = { NULL, NULL, NULL, NULL };
01546   DBusBabysitter *sitter = NULL;
01547   DBusError error = DBUS_ERROR_INIT;
01548   DBusString argv0;
01549 
01550   /*** Test launching segfault binary */
01551 
01552   argv[0] = get_test_exec ("test-segfault", &argv0);
01553 
01554   if (argv[0] == NULL)
01555     {
01556       /* OOM was simulated, never mind */
01557       return TRUE;
01558     }
01559 
01560   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
01561                                          NULL, NULL, NULL,
01562                                          &error))
01563     {
01564       _dbus_babysitter_block_for_child_exit (sitter);
01565       _dbus_babysitter_set_child_exit_error (sitter, &error);
01566     }
01567 
01568   _dbus_string_free (&argv0);
01569 
01570   if (sitter)
01571     _dbus_babysitter_unref (sitter);
01572 
01573   if (!dbus_error_is_set (&error))
01574     {
01575       _dbus_warn ("Did not get an error launching segfaulting binary\n");
01576       return FALSE;
01577     }
01578 
01579   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01580         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01581     {
01582       _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
01583                   error.name, error.message);
01584       dbus_error_free (&error);
01585       return FALSE;
01586     }
01587 
01588   dbus_error_free (&error);
01589   
01590   return TRUE;
01591 }
01592 
01593 static dbus_bool_t
01594 check_spawn_exit (void *data)
01595 {
01596   char *argv[4] = { NULL, NULL, NULL, NULL };
01597   DBusBabysitter *sitter = NULL;
01598   DBusError error = DBUS_ERROR_INIT;
01599   DBusString argv0;
01600 
01601   /*** Test launching exit failure binary */
01602 
01603   argv[0] = get_test_exec ("test-exit", &argv0);
01604 
01605   if (argv[0] == NULL)
01606     {
01607       /* OOM was simulated, never mind */
01608       return TRUE;
01609     }
01610 
01611   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
01612                                          NULL, NULL, NULL,
01613                                          &error))
01614     {
01615       _dbus_babysitter_block_for_child_exit (sitter);
01616       _dbus_babysitter_set_child_exit_error (sitter, &error);
01617     }
01618 
01619   _dbus_string_free (&argv0);
01620 
01621   if (sitter)
01622     _dbus_babysitter_unref (sitter);
01623 
01624   if (!dbus_error_is_set (&error))
01625     {
01626       _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
01627       return FALSE;
01628     }
01629 
01630   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01631         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
01632     {
01633       _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
01634                   error.name, error.message);
01635       dbus_error_free (&error);
01636       return FALSE;
01637     }
01638 
01639   dbus_error_free (&error);
01640   
01641   return TRUE;
01642 }
01643 
01644 static dbus_bool_t
01645 check_spawn_and_kill (void *data)
01646 {
01647   char *argv[4] = { NULL, NULL, NULL, NULL };
01648   DBusBabysitter *sitter = NULL;
01649   DBusError error = DBUS_ERROR_INIT;
01650   DBusString argv0;
01651 
01652   /*** Test launching sleeping binary then killing it */
01653 
01654   argv[0] = get_test_exec ("test-sleep-forever", &argv0);
01655 
01656   if (argv[0] == NULL)
01657     {
01658       /* OOM was simulated, never mind */
01659       return TRUE;
01660     }
01661 
01662   if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
01663                                          NULL, NULL, NULL,
01664                                          &error))
01665     {
01666       _dbus_babysitter_kill_child (sitter);
01667       
01668       _dbus_babysitter_block_for_child_exit (sitter);
01669       
01670       _dbus_babysitter_set_child_exit_error (sitter, &error);
01671     }
01672 
01673   _dbus_string_free (&argv0);
01674 
01675   if (sitter)
01676     _dbus_babysitter_unref (sitter);
01677 
01678   if (!dbus_error_is_set (&error))
01679     {
01680       _dbus_warn ("Did not get an error after killing spawned binary\n");
01681       return FALSE;
01682     }
01683 
01684   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
01685         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01686     {
01687       _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
01688                   error.name, error.message);
01689       dbus_error_free (&error);
01690       return FALSE;
01691     }
01692 
01693   dbus_error_free (&error);
01694   
01695   return TRUE;
01696 }
01697 
01698 dbus_bool_t
01699 _dbus_spawn_test (const char *test_data_dir)
01700 {
01701   if (!_dbus_test_oom_handling ("spawn_nonexistent",
01702                                 check_spawn_nonexistent,
01703                                 NULL))
01704     return FALSE;
01705 
01706   if (!_dbus_test_oom_handling ("spawn_segfault",
01707                                 check_spawn_segfault,
01708                                 NULL))
01709     return FALSE;
01710 
01711   if (!_dbus_test_oom_handling ("spawn_exit",
01712                                 check_spawn_exit,
01713                                 NULL))
01714     return FALSE;
01715 
01716   if (!_dbus_test_oom_handling ("spawn_and_kill",
01717                                 check_spawn_and_kill,
01718                                 NULL))
01719     return FALSE;
01720   
01721   return TRUE;
01722 }
01723 #endif