Coverage report for dbus/dbus-spawn.c.gcov

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