D-Bus 1.4.6

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