ofdbus/dbus/dbus/dbus-spawn.c
changeset 31 ce057bb09d0b
child 45 4b03adbd26ca
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* dbus-spawn.c Wrapper around fork/exec
       
     3  * 
       
     4  * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
       
     5  * Copyright (C) 2003 CodeFactory AB
       
     6  * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     7  * Licensed under the Academic Free License version 2.1
       
     8  * 
       
     9  * This program is free software; you can redistribute it and/or modify
       
    10  * it under the terms of the GNU General Public License as published by
       
    11  * the Free Software Foundation; either version 2 of the License, or
       
    12  * (at your option) any later version.
       
    13  *
       
    14  * This program is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  * GNU General Public License for more details.
       
    18  * 
       
    19  * You should have received a copy of the GNU General Public License
       
    20  * along with this program; if not, write to the Free Software
       
    21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    22  *
       
    23  */
       
    24 #include "dbus-spawn.h"
       
    25 #include "dbus-sysdeps.h"
       
    26 #include "dbus-internals.h"
       
    27 #include "dbus-test.h"
       
    28 #include "dbus-protocol.h"
       
    29 
       
    30 #include <unistd.h>
       
    31 #include <fcntl.h>
       
    32 #ifndef __SYMBIAN32__
       
    33 #include <signal.h>
       
    34 #endif
       
    35 #include <sys/wait.h>
       
    36 #include <errno.h>
       
    37 #include <stdlib.h>
       
    38 #include <spawn.h>
       
    39 #include <pthread.h> 
       
    40 /**
       
    41  * @addtogroup DBusInternalsUtils
       
    42  * @{
       
    43  */
       
    44 
       
    45 /*
       
    46  * I'm pretty sure this whole spawn file could be made simpler,
       
    47  * if you thought about it a bit.
       
    48  */
       
    49 
       
    50 /**
       
    51  * Enumeration for status of a read()
       
    52  */
       
    53 typedef enum
       
    54 {
       
    55   READ_STATUS_OK,    /**< Read succeeded */
       
    56   READ_STATUS_ERROR, /**< Some kind of error */
       
    57   READ_STATUS_EOF    /**< EOF returned */
       
    58 } ReadStatus;
       
    59 
       
    60 static ReadStatus
       
    61 read_ints (int        fd,
       
    62 	   int       *buf,
       
    63 	   int        n_ints_in_buf,
       
    64 	   int       *n_ints_read,
       
    65 	   DBusError *error)
       
    66 {
       
    67   size_t bytes = 0;    
       
    68   ReadStatus retval;
       
    69   
       
    70   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
    71 
       
    72   retval = READ_STATUS_OK;
       
    73   
       
    74   while (TRUE)
       
    75     {
       
    76       size_t chunk;
       
    77       size_t to_read;
       
    78 
       
    79       to_read = sizeof (int) * n_ints_in_buf - bytes;
       
    80 
       
    81       if (to_read == 0)
       
    82         break;
       
    83 
       
    84     again:
       
    85       
       
    86       chunk = read (fd,
       
    87                     ((char*)buf) + bytes,
       
    88                     to_read);
       
    89       
       
    90       if (chunk < 0 && errno == EINTR)
       
    91         goto again;
       
    92           
       
    93       if (chunk < 0)
       
    94         {
       
    95           dbus_set_error (error,
       
    96 			  DBUS_ERROR_SPAWN_FAILED,
       
    97 			  "Failed to read from child pipe (%s)",
       
    98 			  _dbus_strerror (errno));
       
    99 
       
   100           retval = READ_STATUS_ERROR;
       
   101           break;
       
   102         }
       
   103       else if (chunk == 0)
       
   104         {
       
   105           retval = READ_STATUS_EOF;
       
   106           break; /* EOF */
       
   107         }
       
   108       else /* chunk > 0 */
       
   109 	bytes += chunk;
       
   110     }
       
   111 
       
   112   *n_ints_read = (int)(bytes / sizeof(int));
       
   113 
       
   114   return retval;
       
   115 }
       
   116 
       
   117 static ReadStatus
       
   118 read_pid (int        fd,
       
   119           pid_t     *buf,
       
   120           DBusError *error)
       
   121 {
       
   122   size_t bytes = 0;    
       
   123   ReadStatus retval;
       
   124   
       
   125   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
   126 
       
   127   retval = READ_STATUS_OK;
       
   128   
       
   129   while (TRUE)
       
   130     {
       
   131       size_t chunk;    
       
   132       size_t to_read;
       
   133       
       
   134       to_read = sizeof (pid_t) - bytes;
       
   135 
       
   136       if (to_read == 0)
       
   137         break;
       
   138 
       
   139     again:
       
   140       
       
   141       chunk = read (fd,
       
   142                     ((char*)buf) + bytes,
       
   143                     to_read);
       
   144       if (chunk < 0 && errno == EINTR)
       
   145         goto again;
       
   146           
       
   147       if (chunk < 0)
       
   148         {
       
   149           dbus_set_error (error,
       
   150 			  DBUS_ERROR_SPAWN_FAILED,
       
   151 			  "Failed to read from child pipe (%s)",
       
   152 			  _dbus_strerror (errno));
       
   153 
       
   154           retval = READ_STATUS_ERROR;
       
   155           break;
       
   156         }
       
   157       else if (chunk == 0)
       
   158         {
       
   159           retval = READ_STATUS_EOF;
       
   160           break; /* EOF */
       
   161         }
       
   162       else /* chunk > 0 */
       
   163 	bytes += chunk;
       
   164     }
       
   165 
       
   166   return retval;
       
   167 }
       
   168 
       
   169 /* The implementation uses an intermediate child between the main process
       
   170  * and the grandchild. The grandchild is our spawned process. The intermediate
       
   171  * child is a babysitter process; it keeps track of when the grandchild
       
   172  * exits/crashes, and reaps the grandchild.
       
   173  */
       
   174 
       
   175 /* Messages from children to parents */
       
   176 enum
       
   177 {
       
   178   CHILD_EXITED,            /* This message is followed by the exit status int */
       
   179   CHILD_FORK_FAILED,       /* Followed by errno */
       
   180   CHILD_EXEC_FAILED,       /* Followed by errno */
       
   181   CHILD_PID                /* Followed by pid_t */
       
   182 };
       
   183 
       
   184 /**
       
   185  * Babysitter implementation details
       
   186  */
       
   187 struct DBusBabysitter
       
   188 {
       
   189   int refcount; /**< Reference count */
       
   190 
       
   191   char *executable; /**< executable name to use in error messages */
       
   192   
       
   193   int socket_to_babysitter; /**< Connection to the babysitter process */
       
   194   int error_pipe_from_child; /**< Connection to the process that does the exec() */
       
   195   
       
   196   pid_t sitter_pid;  /**< PID Of the babysitter */
       
   197   pid_t grandchild_pid; /**< PID of the grandchild */
       
   198 
       
   199   DBusWatchList *watches; /**< Watches */
       
   200 
       
   201   DBusWatch *error_watch; /**< Error pipe watch */
       
   202   DBusWatch *sitter_watch; /**< Sitter pipe watch */
       
   203 
       
   204   int errnum; /**< Error number */
       
   205   int status; /**< Exit status code */
       
   206   unsigned int have_child_status : 1; /**< True if child status has been reaped */
       
   207   unsigned int have_fork_errnum : 1; /**< True if we have an error code from fork() */
       
   208   unsigned int have_exec_errnum : 1; /**< True if we have an error code from exec() */
       
   209 };
       
   210 
       
   211 static DBusBabysitter*
       
   212 _dbus_babysitter_new (void)
       
   213 {
       
   214   DBusBabysitter *sitter;
       
   215 
       
   216   sitter = dbus_new0 (DBusBabysitter, 1);
       
   217   if (sitter == NULL)
       
   218     return NULL;
       
   219 
       
   220   sitter->refcount = 1;
       
   221 
       
   222   sitter->socket_to_babysitter = -1;
       
   223   sitter->error_pipe_from_child = -1;
       
   224   
       
   225   sitter->sitter_pid = -1;
       
   226   sitter->grandchild_pid = -1;
       
   227 
       
   228   sitter->watches = _dbus_watch_list_new ();
       
   229   if (sitter->watches == NULL)
       
   230     goto failed;
       
   231   
       
   232   return sitter;
       
   233 
       
   234  failed:
       
   235   _dbus_babysitter_unref (sitter);
       
   236   return NULL;
       
   237 }
       
   238 
       
   239 /**
       
   240  * Increment the reference count on the babysitter object.
       
   241  *
       
   242  * @param sitter the babysitter
       
   243  * @returns the babysitter
       
   244  */
       
   245 #ifdef __SYMBIAN32__
       
   246 EXPORT_C
       
   247 #endif
       
   248 DBusBabysitter *
       
   249 _dbus_babysitter_ref (DBusBabysitter *sitter)
       
   250 {
       
   251   _dbus_assert (sitter != NULL);
       
   252   _dbus_assert (sitter->refcount > 0);
       
   253   
       
   254   sitter->refcount += 1;
       
   255 
       
   256   return sitter;
       
   257 }
       
   258 
       
   259 /**
       
   260  * Decrement the reference count on the babysitter object.
       
   261  * When the reference count of the babysitter object reaches
       
   262  * zero, the babysitter is killed and the child that was being
       
   263  * babysat gets emancipated.
       
   264  *
       
   265  * @param sitter the babysitter
       
   266  */
       
   267 #ifdef __SYMBIAN32__
       
   268 EXPORT_C
       
   269 #endif
       
   270 void
       
   271 _dbus_babysitter_unref (DBusBabysitter *sitter)
       
   272 {
       
   273   _dbus_assert (sitter != NULL);
       
   274   _dbus_assert (sitter->refcount > 0);
       
   275   
       
   276   sitter->refcount -= 1;
       
   277   if (sitter->refcount == 0)
       
   278     {      
       
   279       if (sitter->socket_to_babysitter >= 0)
       
   280         {
       
   281           /* If we haven't forked other babysitters
       
   282            * since this babysitter and socket were
       
   283            * created then this close will cause the
       
   284            * babysitter to wake up from poll with
       
   285            * a hangup and then the babysitter will
       
   286            * quit itself.
       
   287            */
       
   288           _dbus_close_socket (sitter->socket_to_babysitter, NULL);
       
   289           sitter->socket_to_babysitter = -1;
       
   290         }
       
   291 
       
   292       if (sitter->error_pipe_from_child >= 0)
       
   293         {
       
   294           _dbus_close_socket (sitter->error_pipe_from_child, NULL);
       
   295           sitter->error_pipe_from_child = -1;
       
   296         }
       
   297 
       
   298       if (sitter->sitter_pid > 0)
       
   299         {
       
   300           int status;
       
   301           int ret;
       
   302 
       
   303           /* It's possible the babysitter died on its own above 
       
   304            * from the close, or was killed randomly
       
   305            * by some other process, so first try to reap it
       
   306            */
       
   307           ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
       
   308 
       
   309           /* If we couldn't reap the child then kill it, and
       
   310            * try again
       
   311            */
       
   312 #ifndef __SYMBIAN32__           
       
   313           if (ret == 0)          
       
   314             kill (sitter->sitter_pid, SIGKILL);
       
   315 #endif          
       
   316 
       
   317         again:
       
   318           if (ret == 0)
       
   319             ret = waitpid (sitter->sitter_pid, &status, 0);
       
   320 
       
   321           if (ret < 0)
       
   322             {
       
   323               if (errno == EINTR)
       
   324                 goto again;
       
   325               else if (errno == ECHILD)
       
   326                 _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
       
   327               else
       
   328                 _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
       
   329                             errno, _dbus_strerror (errno));
       
   330             }
       
   331           else
       
   332             {
       
   333               _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
       
   334                              (long) ret, (long) sitter->sitter_pid);
       
   335               
       
   336               if (WIFEXITED (sitter->status))
       
   337                 _dbus_verbose ("Babysitter exited with status %d\n",
       
   338                                WEXITSTATUS (sitter->status));
       
   339               else if (WIFSIGNALED (sitter->status))
       
   340                 _dbus_verbose ("Babysitter received signal %d\n",
       
   341                                WTERMSIG (sitter->status));
       
   342               else
       
   343                 _dbus_verbose ("Babysitter exited abnormally\n");
       
   344             }
       
   345 
       
   346           sitter->sitter_pid = -1;
       
   347         }
       
   348       
       
   349       if (sitter->error_watch)
       
   350         {
       
   351           _dbus_watch_invalidate (sitter->error_watch);
       
   352           _dbus_watch_unref (sitter->error_watch);
       
   353           sitter->error_watch = NULL;
       
   354         }
       
   355 
       
   356       if (sitter->sitter_watch)
       
   357         {
       
   358           _dbus_watch_invalidate (sitter->sitter_watch);
       
   359           _dbus_watch_unref (sitter->sitter_watch);
       
   360           sitter->sitter_watch = NULL;
       
   361         }
       
   362       
       
   363       if (sitter->watches)
       
   364         _dbus_watch_list_free (sitter->watches);
       
   365 
       
   366       dbus_free (sitter->executable);
       
   367       
       
   368       dbus_free (sitter);
       
   369     }
       
   370 }
       
   371 
       
   372 static ReadStatus
       
   373 read_data (DBusBabysitter *sitter,
       
   374            int             fd)
       
   375 {
       
   376   int what;
       
   377   int got;
       
   378   DBusError error;
       
   379   ReadStatus r;
       
   380   
       
   381   dbus_error_init (&error);
       
   382   
       
   383   r = read_ints (fd, &what, 1, &got, &error);
       
   384 
       
   385   switch (r)
       
   386     {
       
   387     case READ_STATUS_ERROR:
       
   388       _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
       
   389       dbus_error_free (&error);
       
   390       return r;
       
   391 
       
   392     case READ_STATUS_EOF:
       
   393       return r;
       
   394 
       
   395     case READ_STATUS_OK:
       
   396       break;
       
   397     }
       
   398   
       
   399   if (got == 1)
       
   400     {
       
   401       switch (what)
       
   402         {
       
   403         case CHILD_EXITED:
       
   404         case CHILD_FORK_FAILED:
       
   405         case CHILD_EXEC_FAILED:
       
   406           {
       
   407             int arg;
       
   408             
       
   409             r = read_ints (fd, &arg, 1, &got, &error);
       
   410 
       
   411             switch (r)
       
   412               {
       
   413               case READ_STATUS_ERROR:
       
   414                 _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
       
   415                 dbus_error_free (&error);
       
   416                 return r;
       
   417               case READ_STATUS_EOF:
       
   418                 return r;
       
   419               case READ_STATUS_OK:
       
   420                 break;
       
   421               }
       
   422             
       
   423             if (got == 1)
       
   424               {
       
   425                 if (what == CHILD_EXITED)
       
   426                   {
       
   427                     sitter->have_child_status = TRUE;
       
   428                     sitter->status = arg;
       
   429                     _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
       
   430                                    WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
       
   431                                    WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
       
   432                   }
       
   433                 else if (what == CHILD_FORK_FAILED)
       
   434                   {
       
   435                     sitter->have_fork_errnum = TRUE;
       
   436                     sitter->errnum = arg;
       
   437                     _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
       
   438                   }
       
   439                 else if (what == CHILD_EXEC_FAILED)
       
   440                   {
       
   441                     sitter->have_exec_errnum = TRUE;
       
   442                     sitter->errnum = arg;
       
   443                     _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
       
   444                   }
       
   445               }
       
   446           }
       
   447           break;
       
   448         case CHILD_PID:
       
   449           {
       
   450             pid_t pid = -1;
       
   451 
       
   452             r = read_pid (fd, &pid, &error);
       
   453             
       
   454             switch (r)
       
   455               {
       
   456               case READ_STATUS_ERROR:
       
   457                 _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
       
   458                 dbus_error_free (&error);
       
   459                 return r;
       
   460               case READ_STATUS_EOF:
       
   461                 return r;
       
   462               case READ_STATUS_OK:
       
   463                 break;
       
   464               }
       
   465             
       
   466             sitter->grandchild_pid = pid;
       
   467             
       
   468             _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
       
   469           }
       
   470           break;
       
   471         default:
       
   472           _dbus_warn ("Unknown message received from babysitter process\n");
       
   473           break;
       
   474         }
       
   475     }
       
   476 
       
   477   return r;
       
   478 }
       
   479 
       
   480 static void
       
   481 close_socket_to_babysitter (DBusBabysitter *sitter)
       
   482 {
       
   483   _dbus_verbose ("Closing babysitter\n");
       
   484   _dbus_close_socket (sitter->socket_to_babysitter, NULL);
       
   485   sitter->socket_to_babysitter = -1;
       
   486 }
       
   487 
       
   488 static void
       
   489 close_error_pipe_from_child (DBusBabysitter *sitter)
       
   490 {
       
   491   _dbus_verbose ("Closing child error\n");
       
   492   _dbus_close_socket (sitter->error_pipe_from_child, NULL);
       
   493   sitter->error_pipe_from_child = -1;
       
   494 }
       
   495 
       
   496 static void
       
   497 handle_babysitter_socket (DBusBabysitter *sitter,
       
   498                           int             revents)
       
   499 {
       
   500   /* Even if we have POLLHUP, we want to keep reading
       
   501    * data until POLLIN goes away; so this function only
       
   502    * looks at HUP/ERR if no IN is set.
       
   503    */
       
   504   if (revents & _DBUS_POLLIN)
       
   505     {
       
   506       _dbus_verbose ("Reading data from babysitter\n");
       
   507       if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK)
       
   508         close_socket_to_babysitter (sitter);
       
   509     }
       
   510   else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
       
   511     {
       
   512       close_socket_to_babysitter (sitter);
       
   513     }
       
   514 }
       
   515 
       
   516 static void
       
   517 handle_error_pipe (DBusBabysitter *sitter,
       
   518                    int             revents)
       
   519 {
       
   520   if (revents & _DBUS_POLLIN)
       
   521     {
       
   522       _dbus_verbose ("Reading data from child error\n");
       
   523       if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
       
   524         close_error_pipe_from_child (sitter);
       
   525     }
       
   526   else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
       
   527     {
       
   528       close_error_pipe_from_child (sitter);
       
   529     }
       
   530 }
       
   531 
       
   532 /* returns whether there were any poll events handled */
       
   533 static dbus_bool_t
       
   534 babysitter_iteration (DBusBabysitter *sitter,
       
   535                       dbus_bool_t     block)
       
   536 {
       
   537   DBusPollFD fds[2];
       
   538   int i;
       
   539   dbus_bool_t descriptors_ready;
       
   540 
       
   541   descriptors_ready = FALSE;
       
   542   
       
   543   i = 0;
       
   544 
       
   545   if (sitter->error_pipe_from_child >= 0)
       
   546     {
       
   547       fds[i].fd = sitter->error_pipe_from_child;
       
   548       fds[i].events = _DBUS_POLLIN;
       
   549       fds[i].revents = 0;
       
   550       ++i;
       
   551     }
       
   552   
       
   553   if (sitter->socket_to_babysitter >= 0)
       
   554     {
       
   555       fds[i].fd = sitter->socket_to_babysitter;
       
   556       fds[i].events = _DBUS_POLLIN;
       
   557       fds[i].revents = 0;
       
   558       ++i;
       
   559     }
       
   560 
       
   561   if (i > 0)
       
   562     {
       
   563       int ret;
       
   564 
       
   565       ret = _dbus_poll (fds, i, 0);
       
   566       if (ret == 0 && block)
       
   567         ret = _dbus_poll (fds, i, -1);
       
   568       
       
   569       if (ret > 0)
       
   570         {
       
   571           descriptors_ready = TRUE;
       
   572           
       
   573           while (i > 0)
       
   574             {
       
   575               --i;
       
   576               if (fds[i].fd == sitter->error_pipe_from_child)
       
   577                 handle_error_pipe (sitter, fds[i].revents);
       
   578               else if (fds[i].fd == sitter->socket_to_babysitter)
       
   579                 handle_babysitter_socket (sitter, fds[i].revents);
       
   580             }
       
   581         }
       
   582     }
       
   583 
       
   584   return descriptors_ready;
       
   585 }
       
   586 
       
   587 /**
       
   588  * Macro returns #TRUE if the babysitter still has live sockets open to the
       
   589  * babysitter child or the grandchild.
       
   590  */
       
   591 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
       
   592 
       
   593 /**
       
   594  * Blocks until the babysitter process gives us the PID of the spawned grandchild,
       
   595  * then kills the spawned grandchild.
       
   596  *
       
   597  * @param sitter the babysitter object
       
   598  */
       
   599 #ifdef __SYMBIAN32__
       
   600 EXPORT_C
       
   601 #endif
       
   602 void
       
   603 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
       
   604 {
       
   605   /* be sure we have the PID of the child */
       
   606   while (LIVE_CHILDREN (sitter) &&
       
   607          sitter->grandchild_pid == -1)
       
   608     babysitter_iteration (sitter, TRUE);
       
   609 
       
   610   _dbus_verbose ("Got child PID %ld for killing\n",
       
   611                  (long) sitter->grandchild_pid);
       
   612   
       
   613   if (sitter->grandchild_pid == -1)
       
   614     return; /* child is already dead, or we're so hosed we'll never recover */
       
   615 #ifndef __SYMBIAN32__
       
   616   kill (sitter->grandchild_pid, SIGKILL);
       
   617 #endif  
       
   618 }
       
   619 
       
   620 /**
       
   621  * Checks whether the child has exited, without blocking.
       
   622  *
       
   623  * @param sitter the babysitter
       
   624  */
       
   625 #ifdef __SYMBIAN32__
       
   626 EXPORT_C
       
   627 #endif
       
   628 dbus_bool_t
       
   629 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
       
   630 {
       
   631 
       
   632   /* Be sure we're up-to-date */
       
   633   while (LIVE_CHILDREN (sitter) &&
       
   634          babysitter_iteration (sitter, FALSE))
       
   635     ;
       
   636 
       
   637   /* We will have exited the babysitter when the child has exited */
       
   638   return sitter->socket_to_babysitter < 0;
       
   639 }
       
   640 
       
   641 /**
       
   642  * Sets the #DBusError with an explanation of why the spawned
       
   643  * child process exited (on a signal, or whatever). If
       
   644  * the child process has not exited, does nothing (error
       
   645  * will remain unset).
       
   646  *
       
   647  * @param sitter the babysitter
       
   648  * @param error an error to fill in
       
   649  */
       
   650 #ifdef __SYMBIAN32__
       
   651 EXPORT_C
       
   652 #endif
       
   653 void
       
   654 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
       
   655                                        DBusError      *error)
       
   656 {
       
   657   if (!_dbus_babysitter_get_child_exited (sitter))
       
   658     return;
       
   659 
       
   660   /* Note that if exec fails, we will also get a child status
       
   661    * from the babysitter saying the child exited,
       
   662    * so we need to give priority to the exec error
       
   663    */
       
   664   if (sitter->have_exec_errnum)
       
   665     {
       
   666       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
       
   667                       "Failed to execute program %s: %s",
       
   668                       sitter->executable, _dbus_strerror (sitter->errnum));
       
   669     }
       
   670   else if (sitter->have_fork_errnum)
       
   671     {
       
   672       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
       
   673                       "Failed to fork a new process %s: %s",
       
   674                       sitter->executable, _dbus_strerror (sitter->errnum));
       
   675     }
       
   676   else if (sitter->have_child_status)
       
   677     {
       
   678       if (WIFEXITED (sitter->status))
       
   679         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
       
   680                         "Process %s exited with status %d",
       
   681                         sitter->executable, WEXITSTATUS (sitter->status));
       
   682       else if (WIFSIGNALED (sitter->status))
       
   683         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
       
   684                         "Process %s received signal %d",
       
   685                         sitter->executable, WTERMSIG (sitter->status));
       
   686       else
       
   687         dbus_set_error (error, DBUS_ERROR_FAILED,
       
   688                         "Process %s exited abnormally",
       
   689                         sitter->executable);
       
   690     }
       
   691   else
       
   692     {
       
   693       dbus_set_error (error, DBUS_ERROR_FAILED,
       
   694                       "Process %s exited, reason unknown",
       
   695                       sitter->executable);
       
   696     }
       
   697 }
       
   698 
       
   699 /**
       
   700  * Sets watch functions to notify us when the
       
   701  * babysitter object needs to read/write file descriptors.
       
   702  *
       
   703  * @param sitter the babysitter
       
   704  * @param add_function function to begin monitoring a new descriptor.
       
   705  * @param remove_function function to stop monitoring a descriptor.
       
   706  * @param toggled_function function to notify when the watch is enabled/disabled
       
   707  * @param data data to pass to add_function and remove_function.
       
   708  * @param free_data_function function to be called to free the data.
       
   709  * @returns #FALSE on failure (no memory)
       
   710  */
       
   711 #ifdef __SYMBIAN32__
       
   712 EXPORT_C
       
   713 #endif
       
   714 dbus_bool_t
       
   715 _dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
       
   716                                       DBusAddWatchFunction       add_function,
       
   717                                       DBusRemoveWatchFunction    remove_function,
       
   718                                       DBusWatchToggledFunction   toggled_function,
       
   719                                       void                      *data,
       
   720                                       DBusFreeFunction           free_data_function)
       
   721 {
       
   722   return _dbus_watch_list_set_functions (sitter->watches,
       
   723                                          add_function,
       
   724                                          remove_function,
       
   725                                          toggled_function,
       
   726                                          data,
       
   727                                          free_data_function);
       
   728 }
       
   729 
       
   730 static dbus_bool_t
       
   731 handle_watch (DBusWatch       *watch,
       
   732               unsigned int     condition,
       
   733               void            *data)
       
   734 {
       
   735   DBusBabysitter *sitter = data;
       
   736   int revents;
       
   737   int fd;
       
   738   
       
   739   revents = 0;
       
   740   if (condition & DBUS_WATCH_READABLE)
       
   741     revents |= _DBUS_POLLIN;
       
   742   if (condition & DBUS_WATCH_ERROR)
       
   743     revents |= _DBUS_POLLERR;
       
   744   if (condition & DBUS_WATCH_HANGUP)
       
   745     revents |= _DBUS_POLLHUP;
       
   746 
       
   747   fd = dbus_watch_get_fd (watch);
       
   748 
       
   749   if (fd == sitter->error_pipe_from_child)
       
   750     handle_error_pipe (sitter, revents);
       
   751   else if (fd == sitter->socket_to_babysitter)
       
   752     handle_babysitter_socket (sitter, revents);
       
   753 
       
   754   while (LIVE_CHILDREN (sitter) &&
       
   755          babysitter_iteration (sitter, FALSE))
       
   756     ;
       
   757   
       
   758   return TRUE;
       
   759 }
       
   760 
       
   761 /** Helps remember which end of the pipe is which */
       
   762 #define READ_END 0
       
   763 /** Helps remember which end of the pipe is which */
       
   764 #define WRITE_END 1
       
   765 
       
   766 
       
   767 /* Avoids a danger in threaded situations (calling close()
       
   768  * on a file descriptor twice, and another thread has
       
   769  * re-opened it since the first close)
       
   770  */
       
   771 static int
       
   772 close_and_invalidate (int *fd)
       
   773 {
       
   774   int ret;
       
   775 
       
   776   if (*fd < 0)
       
   777     return -1;
       
   778   else
       
   779     {
       
   780       ret = _dbus_close_socket (*fd, NULL);
       
   781       *fd = -1;
       
   782     }
       
   783 
       
   784   return ret;
       
   785 }
       
   786 
       
   787 static dbus_bool_t
       
   788 make_pipe (int         p[2],
       
   789            DBusError  *error)
       
   790 {
       
   791   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
   792   
       
   793   if (pipe (p) < 0)
       
   794     {
       
   795       dbus_set_error (error,
       
   796 		      DBUS_ERROR_SPAWN_FAILED,
       
   797 		      "Failed to create pipe for communicating with child process (%s)",
       
   798 		      _dbus_strerror (errno));
       
   799       return FALSE;
       
   800     }
       
   801 
       
   802   return TRUE;
       
   803 }
       
   804 
       
   805 static void
       
   806 do_write (int fd, const void *buf, size_t count)
       
   807 {
       
   808   size_t bytes_written;
       
   809   int ret;
       
   810   
       
   811   bytes_written = 0;
       
   812   
       
   813  again:
       
   814   
       
   815   ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
       
   816 
       
   817   if (ret < 0)
       
   818     {
       
   819       if (errno == EINTR)
       
   820         goto again;
       
   821       else
       
   822         {
       
   823           _dbus_warn ("Failed to write data to pipe!\n");
       
   824           exit (1); /* give up, we suck */
       
   825         }
       
   826     }
       
   827   else
       
   828     bytes_written += ret;
       
   829   
       
   830   if (bytes_written < count)
       
   831     goto again;
       
   832 }
       
   833 
       
   834 static void
       
   835 write_err_and_exit (int fd, int msg)
       
   836 {
       
   837   int en = errno;
       
   838 
       
   839   do_write (fd, &msg, sizeof (msg));
       
   840   do_write (fd, &en, sizeof (en));
       
   841   
       
   842   exit (1);
       
   843 }
       
   844 
       
   845 static void
       
   846 write_pid (int fd, pid_t pid)
       
   847 {
       
   848   int msg = CHILD_PID;
       
   849   
       
   850   do_write (fd, &msg, sizeof (msg));
       
   851   do_write (fd, &pid, sizeof (pid));
       
   852 }
       
   853 
       
   854 static void
       
   855 write_status_and_exit (int fd, int status)
       
   856 {
       
   857   int msg = CHILD_EXITED;
       
   858   
       
   859   do_write (fd, &msg, sizeof (msg));
       
   860   do_write (fd, &status, sizeof (status));
       
   861   
       
   862   exit (0);
       
   863 }
       
   864 
       
   865 static void
       
   866 do_exec (int                       child_err_report_fd,
       
   867 	 char                    **argv,
       
   868 	 DBusSpawnChildSetupFunc   child_setup,
       
   869 	 void                     *user_data)
       
   870 {
       
   871 #ifdef DBUS_BUILD_TESTS
       
   872   int i, max_open;
       
   873 #endif
       
   874 
       
   875   _dbus_verbose_reset ();
       
   876   _dbus_verbose ("Child process has PID %lu\n",
       
   877                  _dbus_getpid ());
       
   878   
       
   879   if (child_setup)
       
   880     (* child_setup) (user_data);
       
   881 
       
   882 #ifdef DBUS_BUILD_TESTS
       
   883   max_open = sysconf (_SC_OPEN_MAX);
       
   884   
       
   885   for (i = 3; i < max_open; i++)
       
   886     {
       
   887       int retval;
       
   888 
       
   889       if (i == child_err_report_fd)
       
   890         continue;
       
   891       
       
   892       retval = fcntl (i, F_GETFD);
       
   893 
       
   894       if (retval != -1 && !(retval & FD_CLOEXEC))
       
   895 	_dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
       
   896     }
       
   897 #endif
       
   898   #ifndef __SYMBIAN32__
       
   899   execv (argv[0], argv);
       
   900   #endif
       
   901   /* Exec failed */
       
   902   write_err_and_exit (child_err_report_fd,
       
   903                       CHILD_EXEC_FAILED);
       
   904 }
       
   905 
       
   906 static void
       
   907 check_babysit_events (pid_t grandchild_pid,
       
   908                       int   parent_pipe,
       
   909                       int   revents)
       
   910 {
       
   911   pid_t ret;
       
   912   int status;
       
   913   
       
   914   do
       
   915     {
       
   916       ret = waitpid (grandchild_pid, &status, WNOHANG);
       
   917       /* The man page says EINTR can't happen with WNOHANG,
       
   918        * but there are reports of it (maybe only with valgrind?)
       
   919        */
       
   920     }
       
   921   while (ret < 0 && errno == EINTR);
       
   922 
       
   923   if (ret == 0)
       
   924     {
       
   925       _dbus_verbose ("no child exited\n");
       
   926       
       
   927       ; /* no child exited */
       
   928     }
       
   929   else if (ret < 0)
       
   930     {
       
   931       /* This isn't supposed to happen. */
       
   932       _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
       
   933                   _dbus_strerror (errno));
       
   934       exit (1);
       
   935     }
       
   936   else if (ret == grandchild_pid)
       
   937     {
       
   938       /* Child exited */
       
   939       _dbus_verbose ("reaped child pid %ld\n", (long) ret);
       
   940       
       
   941       write_status_and_exit (parent_pipe, status);
       
   942     }
       
   943   else
       
   944     {
       
   945       _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
       
   946                   (int) ret);
       
   947       exit (1);
       
   948     }
       
   949 
       
   950   if (revents & _DBUS_POLLIN)
       
   951     {
       
   952       _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
       
   953     }
       
   954 
       
   955   if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
       
   956     {
       
   957       /* Parent is gone, so we just exit */
       
   958       _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
       
   959       exit (0);
       
   960     }
       
   961 }
       
   962 
       
   963 static int babysit_sigchld_pipe = -1;
       
   964 
       
   965 static void
       
   966 babysit_signal_handler (int signo)
       
   967 {
       
   968   char b = '\0';
       
   969  again:
       
   970   write (babysit_sigchld_pipe, &b, 1);
       
   971   if (errno == EINTR)
       
   972     goto again;
       
   973 }
       
   974 
       
   975 static void
       
   976 babysit (pid_t grandchild_pid,
       
   977          int   parent_pipe)
       
   978 {
       
   979   int sigchld_pipe[2];
       
   980 
       
   981   /* We don't exec, so we keep parent state, such as the pid that
       
   982    * _dbus_verbose() uses. Reset the pid here.
       
   983    */
       
   984   _dbus_verbose_reset ();
       
   985   
       
   986   /* I thought SIGCHLD would just wake up the poll, but
       
   987    * that didn't seem to work, so added this pipe.
       
   988    * Probably the pipe is more likely to work on busted
       
   989    * operating systems anyhow.
       
   990    */
       
   991   if (pipe (sigchld_pipe) < 0)
       
   992     {
       
   993       _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
       
   994       exit (1);
       
   995     }
       
   996 
       
   997   babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
       
   998 #ifndef __SYMBIAN32__
       
   999   _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
       
  1000 #endif  
       
  1001   
       
  1002   write_pid (parent_pipe, grandchild_pid);
       
  1003 
       
  1004   check_babysit_events (grandchild_pid, parent_pipe, 0);
       
  1005 
       
  1006   while (TRUE)
       
  1007     {
       
  1008       DBusPollFD pfds[2];
       
  1009       
       
  1010       pfds[0].fd = parent_pipe;
       
  1011       pfds[0].events = _DBUS_POLLIN;
       
  1012       pfds[0].revents = 0;
       
  1013 
       
  1014       pfds[1].fd = sigchld_pipe[READ_END];
       
  1015       pfds[1].events = _DBUS_POLLIN;
       
  1016       pfds[1].revents = 0;
       
  1017       
       
  1018       _dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1);
       
  1019 
       
  1020       if (pfds[0].revents != 0)
       
  1021         {
       
  1022           check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
       
  1023         }
       
  1024       else if (pfds[1].revents & _DBUS_POLLIN)
       
  1025         {
       
  1026           char b;
       
  1027           read (sigchld_pipe[READ_END], &b, 1);
       
  1028           /* do waitpid check */
       
  1029           check_babysit_events (grandchild_pid, parent_pipe, 0);
       
  1030         }
       
  1031     }
       
  1032   
       
  1033   exit (1);
       
  1034 }
       
  1035 
       
  1036 /**
       
  1037  * Spawns a new process. The executable name and argv[0]
       
  1038  * are the same, both are provided in argv[0]. The child_setup
       
  1039  * function is passed the given user_data and is run in the child
       
  1040  * just before calling exec().
       
  1041  *
       
  1042  * Also creates a "babysitter" which tracks the status of the
       
  1043  * child process, advising the parent if the child exits.
       
  1044  * If the spawn fails, no babysitter is created.
       
  1045  * If sitter_p is #NULL, no babysitter is kept.
       
  1046  *
       
  1047  * @param sitter_p return location for babysitter or #NULL
       
  1048  * @param argv the executable and arguments
       
  1049  * @param child_setup function to call in child pre-exec()
       
  1050  * @param user_data user data for setup function
       
  1051  * @param error error object to be filled in if function fails
       
  1052  * @returns #TRUE on success, #FALSE if error is filled in
       
  1053  */
       
  1054 #ifdef __SYMBIAN32__
       
  1055 #include <stdio.h>
       
  1056 #include <sys/types.h>
       
  1057 #include <sys/stat.h>
       
  1058 #include <sys/time.h>
       
  1059 #include <unistd.h>
       
  1060 #include <fcntl.h>
       
  1061 #include <sys/select.h>
       
  1062 #include <stdlib.h>
       
  1063 #include <string.h>
       
  1064 
       
  1065 
       
  1066 void thread_fun();
       
  1067 
       
  1068 
       
  1069 
       
  1070 #endif 
       
  1071  
       
  1072 #ifdef __SYMBIAN32__
       
  1073 EXPORT_C
       
  1074 #endif
       
  1075 dbus_bool_t
       
  1076 _dbus_spawn_async_with_babysitter (DBusBabysitter          **sitter_p,
       
  1077                                    char                    **argv,
       
  1078                                    DBusSpawnChildSetupFunc   child_setup,
       
  1079                                    void                     *user_data,
       
  1080                                    DBusError                *error)
       
  1081 {
       
  1082 
       
  1083 #ifndef __SYMBIAN32__
       
  1084   DBusBabysitter *sitter;
       
  1085   int child_err_report_pipe[2] = { -1, -1 };
       
  1086   int babysitter_pipe[2] = { -1, -1 };
       
  1087   pid_t pid;
       
  1088   
       
  1089   #ifndef __SYMBIAN32__
       
  1090   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
  1091 
       
  1092   *sitter_p = NULL;
       
  1093   sitter = NULL;
       
  1094 
       
  1095   sitter = _dbus_babysitter_new ();
       
  1096   if (sitter == NULL)
       
  1097     {
       
  1098       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
       
  1099       return FALSE;
       
  1100     }
       
  1101 
       
  1102   sitter->executable = _dbus_strdup (argv[0]);
       
  1103   if (sitter->executable == NULL)
       
  1104     {
       
  1105       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
       
  1106       goto cleanup_and_fail;
       
  1107     }
       
  1108   
       
  1109   if (!make_pipe (child_err_report_pipe, error))
       
  1110     goto cleanup_and_fail;
       
  1111 
       
  1112   _dbus_fd_set_close_on_exec (child_err_report_pipe[READ_END]);
       
  1113   _dbus_fd_set_close_on_exec (child_err_report_pipe[WRITE_END]);
       
  1114 
       
  1115   if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
       
  1116     goto cleanup_and_fail;
       
  1117 
       
  1118   _dbus_fd_set_close_on_exec (babysitter_pipe[0]);
       
  1119   _dbus_fd_set_close_on_exec (babysitter_pipe[1]);
       
  1120 
       
  1121   /* Setting up the babysitter is only useful in the parent,
       
  1122    * but we don't want to run out of memory and fail
       
  1123    * after we've already forked, since then we'd leak
       
  1124    * child processes everywhere.
       
  1125    */
       
  1126   sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
       
  1127                                          DBUS_WATCH_READABLE,
       
  1128                                          TRUE, handle_watch, sitter, NULL);
       
  1129   if (sitter->error_watch == NULL)
       
  1130     {
       
  1131       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
       
  1132       goto cleanup_and_fail;
       
  1133     }
       
  1134         
       
  1135   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->error_watch))
       
  1136     {
       
  1137       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
       
  1138       goto cleanup_and_fail;
       
  1139     }
       
  1140       
       
  1141   sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0],
       
  1142                                           DBUS_WATCH_READABLE,
       
  1143                                           TRUE, handle_watch, sitter, NULL);
       
  1144   if (sitter->sitter_watch == NULL)
       
  1145     {
       
  1146       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
       
  1147       goto cleanup_and_fail;
       
  1148     }
       
  1149       
       
  1150   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
       
  1151     {
       
  1152       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
       
  1153       goto cleanup_and_fail;
       
  1154     }
       
  1155 
       
  1156   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
  1157   
       
  1158   pid = fork ();
       
  1159   
       
  1160   if (pid < 0)
       
  1161     {
       
  1162       dbus_set_error (error,
       
  1163 		      DBUS_ERROR_SPAWN_FORK_FAILED,
       
  1164 		      "Failed to fork (%s)",
       
  1165 		      _dbus_strerror (errno));
       
  1166       goto cleanup_and_fail;
       
  1167     }
       
  1168   else if (pid == 0)
       
  1169     {
       
  1170       /* Immediate child, this is the babysitter process. */
       
  1171       int grandchild_pid;
       
  1172       
       
  1173       /* Be sure we crash if the parent exits
       
  1174        * and we write to the err_report_pipe
       
  1175        */
       
  1176 #ifndef __SYMBIAN32__       
       
  1177       signal (SIGPIPE, SIG_DFL);
       
  1178 #endif      
       
  1179 
       
  1180       /* Close the parent's end of the pipes. */
       
  1181       close_and_invalidate (&child_err_report_pipe[READ_END]);
       
  1182       close_and_invalidate (&babysitter_pipe[0]);
       
  1183       
       
  1184       /* Create the child that will exec () */
       
  1185       grandchild_pid = fork ();
       
  1186       
       
  1187       if (grandchild_pid < 0)
       
  1188 	{
       
  1189 	  write_err_and_exit (babysitter_pipe[1],
       
  1190 			      CHILD_FORK_FAILED);
       
  1191           _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
       
  1192 	}
       
  1193       else if (grandchild_pid == 0)
       
  1194 	{
       
  1195 	  do_exec (child_err_report_pipe[WRITE_END],
       
  1196 		   argv,
       
  1197 		   child_setup, user_data);
       
  1198           _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
       
  1199 	}
       
  1200       else
       
  1201 	{
       
  1202           babysit (grandchild_pid, babysitter_pipe[1]);
       
  1203           _dbus_assert_not_reached ("Got to code after babysit()");
       
  1204 	}
       
  1205     }
       
  1206   else
       
  1207     {      
       
  1208       /* Close the uncared-about ends of the pipes */
       
  1209       close_and_invalidate (&child_err_report_pipe[WRITE_END]);
       
  1210       close_and_invalidate (&babysitter_pipe[1]);
       
  1211 
       
  1212       sitter->socket_to_babysitter = babysitter_pipe[0];
       
  1213       babysitter_pipe[0] = -1;
       
  1214       
       
  1215       sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
       
  1216       child_err_report_pipe[READ_END] = -1;
       
  1217 
       
  1218       sitter->sitter_pid = pid;
       
  1219 
       
  1220       if (sitter_p != NULL)
       
  1221         *sitter_p = sitter;
       
  1222       else
       
  1223         _dbus_babysitter_unref (sitter);
       
  1224 
       
  1225       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
  1226       
       
  1227       return TRUE;
       
  1228     }
       
  1229 
       
  1230  cleanup_and_fail:
       
  1231 
       
  1232   _DBUS_ASSERT_ERROR_IS_SET (error);
       
  1233   
       
  1234   close_and_invalidate (&child_err_report_pipe[READ_END]);
       
  1235   close_and_invalidate (&child_err_report_pipe[WRITE_END]);
       
  1236   close_and_invalidate (&babysitter_pipe[0]);
       
  1237   close_and_invalidate (&babysitter_pipe[1]);
       
  1238 
       
  1239   if (sitter != NULL)
       
  1240     _dbus_babysitter_unref (sitter);
       
  1241   #endif
       
  1242   return FALSE;
       
  1243   
       
  1244   
       
  1245 #else
       
  1246 
       
  1247 
       
  1248 /*
       
  1249 FILE* ChildProcessStream;
       
  1250  ChildProcessStream =popen(argv[0], "r");
       
  1251 	if (ChildProcessStream == NULL)
       
  1252 	{
       
  1253 	 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
       
  1254                       "Failed to execute service process");
       
  1255      	 return FALSE;
       
  1256       
       
  1257 	}
       
  1258 */
       
  1259  //static pid_t Childpid; //have to make it static for thread fuction to access it
       
  1260  pid_t childPid;
       
  1261  int retVal; 
       
  1262  
       
  1263  //pthread_t thread;
       
  1264 
       
  1265  retVal = posix_spawn(&childPid, argv[0], NULL,NULL, NULL, NULL);
       
  1266   	if (retVal!=0)
       
  1267 	{
       
  1268 	 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
       
  1269                       "Failed to execute service process");
       
  1270      	 return FALSE;
       
  1271       
       
  1272 	}
       
  1273 
       
  1274 /*
       
  1275  pthread_create(&thread, NULL, (void*)&thread_fun, &Childpid);
       
  1276 //(void) waitpid(Childpid, NULL, 0);
       
  1277 //printf("\r\n*** Child process finished ***\r\n");
       
  1278 
       
  1279 */
       
  1280 
       
  1281 if(!retVal)
       
  1282 	return TRUE;
       
  1283 else
       
  1284 	return FALSE;
       
  1285 
       
  1286 #endif  
       
  1287 }
       
  1288 
       
  1289 /** @} */
       
  1290 /*
       
  1291 void thread_fun(void *data)
       
  1292 {
       
  1293 	pid_t *Childpid= (pid_t*)data;
       
  1294 	(void) waitpid(*Childpid, NULL, 0);
       
  1295 	printf("\n service terminated");
       
  1296 }
       
  1297 
       
  1298 */
       
  1299 
       
  1300 
       
  1301 #ifdef DBUS_BUILD_TESTS
       
  1302 
       
  1303 static void
       
  1304 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
       
  1305 {
       
  1306   while (LIVE_CHILDREN (sitter))
       
  1307     babysitter_iteration (sitter, TRUE);
       
  1308 }
       
  1309 
       
  1310 static dbus_bool_t
       
  1311 check_spawn_nonexistent (void *data)
       
  1312 {
       
  1313   char *argv[4] = { NULL, NULL, NULL, NULL };
       
  1314   DBusBabysitter *sitter;
       
  1315   DBusError error;
       
  1316   
       
  1317   sitter = NULL;
       
  1318   
       
  1319   dbus_error_init (&error);
       
  1320 
       
  1321   /*** Test launching nonexistent binary */
       
  1322   
       
  1323   argv[0] = "/this/does/not/exist/32542sdgafgafdg";
       
  1324   if (_dbus_spawn_async_with_babysitter (&sitter, argv,
       
  1325                                          NULL, NULL,
       
  1326                                          &error))
       
  1327     {
       
  1328       _dbus_babysitter_block_for_child_exit (sitter);
       
  1329       _dbus_babysitter_set_child_exit_error (sitter, &error);
       
  1330     }
       
  1331 
       
  1332   if (sitter)
       
  1333     _dbus_babysitter_unref (sitter);
       
  1334 
       
  1335   if (!dbus_error_is_set (&error))
       
  1336     {
       
  1337       _dbus_warn ("Did not get an error launching nonexistent executable\n");
       
  1338       return FALSE;
       
  1339     }
       
  1340 
       
  1341   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
       
  1342         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
       
  1343     {
       
  1344       _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
       
  1345                   error.name, error.message);
       
  1346       dbus_error_free (&error);
       
  1347       return FALSE;
       
  1348     }
       
  1349 
       
  1350   dbus_error_free (&error);
       
  1351   
       
  1352   return TRUE;
       
  1353 }
       
  1354 
       
  1355 static dbus_bool_t
       
  1356 check_spawn_segfault (void *data)
       
  1357 {
       
  1358   char *argv[4] = { NULL, NULL, NULL, NULL };
       
  1359   DBusBabysitter *sitter;
       
  1360   DBusError error;
       
  1361   
       
  1362   sitter = NULL;
       
  1363   
       
  1364   dbus_error_init (&error);
       
  1365 
       
  1366   /*** Test launching segfault binary */
       
  1367   
       
  1368   argv[0] = TEST_SEGFAULT_BINARY;
       
  1369   if (_dbus_spawn_async_with_babysitter (&sitter, argv,
       
  1370                                          NULL, NULL,
       
  1371                                          &error))
       
  1372     {
       
  1373       _dbus_babysitter_block_for_child_exit (sitter);
       
  1374       _dbus_babysitter_set_child_exit_error (sitter, &error);
       
  1375     }
       
  1376 
       
  1377   if (sitter)
       
  1378     _dbus_babysitter_unref (sitter);
       
  1379 
       
  1380   if (!dbus_error_is_set (&error))
       
  1381     {
       
  1382       _dbus_warn ("Did not get an error launching segfaulting binary\n");
       
  1383       return FALSE;
       
  1384     }
       
  1385 
       
  1386   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
       
  1387         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
       
  1388     {
       
  1389       _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
       
  1390                   error.name, error.message);
       
  1391       dbus_error_free (&error);
       
  1392       return FALSE;
       
  1393     }
       
  1394 
       
  1395   dbus_error_free (&error);
       
  1396   
       
  1397   return TRUE;
       
  1398 }
       
  1399 
       
  1400 static dbus_bool_t
       
  1401 check_spawn_exit (void *data)
       
  1402 {
       
  1403   char *argv[4] = { NULL, NULL, NULL, NULL };
       
  1404   DBusBabysitter *sitter;
       
  1405   DBusError error;
       
  1406   
       
  1407   sitter = NULL;
       
  1408   
       
  1409   dbus_error_init (&error);
       
  1410 
       
  1411   /*** Test launching exit failure binary */
       
  1412   
       
  1413   argv[0] = TEST_EXIT_BINARY;
       
  1414   if (_dbus_spawn_async_with_babysitter (&sitter, argv,
       
  1415                                          NULL, NULL,
       
  1416                                          &error))
       
  1417     {
       
  1418     #ifdef __SYMBIAN32__
       
  1419     if(sitter)
       
  1420     {
       
  1421     #endif
       
  1422       _dbus_babysitter_block_for_child_exit (sitter);
       
  1423       _dbus_babysitter_set_child_exit_error (sitter, &error);
       
  1424       
       
  1425     #ifdef __SYMBIAN32__
       
  1426     }
       
  1427     #endif
       
  1428       /* no baby sitter support in Symbian */
       
  1429     }
       
  1430 
       
  1431   if (sitter)
       
  1432     _dbus_babysitter_unref (sitter);
       
  1433 
       
  1434   if (!dbus_error_is_set (&error))
       
  1435     {
       
  1436       _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
       
  1437       return FALSE;
       
  1438     }
       
  1439 
       
  1440   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
       
  1441         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
       
  1442     {
       
  1443       _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
       
  1444                   error.name, error.message);
       
  1445       dbus_error_free (&error);
       
  1446       return FALSE;
       
  1447     }
       
  1448 
       
  1449   dbus_error_free (&error);
       
  1450   
       
  1451   return TRUE;
       
  1452 }
       
  1453 
       
  1454 static dbus_bool_t
       
  1455 check_spawn_and_kill (void *data)
       
  1456 {
       
  1457   char *argv[4] = { NULL, NULL, NULL, NULL };
       
  1458   DBusBabysitter *sitter;
       
  1459   DBusError error;
       
  1460   
       
  1461   sitter = NULL;
       
  1462   
       
  1463   dbus_error_init (&error);
       
  1464 
       
  1465   /*** Test launching sleeping binary then killing it */
       
  1466 
       
  1467   argv[0] = TEST_SLEEP_FOREVER_BINARY;
       
  1468   if (_dbus_spawn_async_with_babysitter (&sitter, argv,
       
  1469                                          NULL, NULL,
       
  1470                                          &error))
       
  1471     {
       
  1472       _dbus_babysitter_kill_child (sitter);
       
  1473       
       
  1474       _dbus_babysitter_block_for_child_exit (sitter);
       
  1475       
       
  1476       _dbus_babysitter_set_child_exit_error (sitter, &error);
       
  1477     }
       
  1478 
       
  1479   if (sitter)
       
  1480     _dbus_babysitter_unref (sitter);
       
  1481 
       
  1482   if (!dbus_error_is_set (&error))
       
  1483     {
       
  1484       _dbus_warn ("Did not get an error after killing spawned binary\n");
       
  1485       return FALSE;
       
  1486     }
       
  1487 
       
  1488   if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
       
  1489         dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
       
  1490     {
       
  1491       _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
       
  1492                   error.name, error.message);
       
  1493       dbus_error_free (&error);
       
  1494       return FALSE;
       
  1495     }
       
  1496 
       
  1497   dbus_error_free (&error);
       
  1498   
       
  1499   return TRUE;
       
  1500 }
       
  1501 
       
  1502 #ifdef __SYMBIAN32__
       
  1503 EXPORT_C
       
  1504 #endif
       
  1505 dbus_bool_t
       
  1506 _dbus_spawn_test (const char *test_data_dir)
       
  1507 {
       
  1508   if (!_dbus_test_oom_handling ("spawn_nonexistent",
       
  1509                                 check_spawn_nonexistent,
       
  1510                                 NULL))
       
  1511     return FALSE;
       
  1512     
       
  1513    #ifndef __SYMBIAN32__ 
       
  1514 
       
  1515   if (!_dbus_test_oom_handling ("spawn_segfault",
       
  1516                                 check_spawn_segfault,
       
  1517                                 NULL))
       
  1518     return FALSE;
       
  1519    #endif  // No signal support in Symbian
       
  1520    
       
  1521     #ifndef __SYMBIAN32__ 
       
  1522   if (!_dbus_test_oom_handling ("spawn_exit",
       
  1523                                 check_spawn_exit,
       
  1524                                 NULL))
       
  1525     return FALSE;
       
  1526     
       
  1527      #endif  // No baby sitter support in Symbian
       
  1528  #ifndef __SYMBIAN32__ 
       
  1529   if (!_dbus_test_oom_handling ("spawn_and_kill",
       
  1530                                 check_spawn_and_kill,
       
  1531                                 NULL))
       
  1532     return FALSE;
       
  1533   #endif  // No signal support in Symbian
       
  1534   return TRUE;
       
  1535 }
       
  1536 #endif