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