dbus-spawn.c 46.5 KB
Newer Older
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 3
/* dbus-spawn.c Wrapper around fork/exec
 * 
4
 * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
5 6
 * Copyright (C) 2003 CodeFactory AB
 *
7
 * Licensed under the Academic Free License version 2.1
8 9 10 11 12 13 14 15 16 17 18 19 20
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 23
 *
 */
24 25 26

#include <config.h>

27
#include "dbus-spawn.h"
28
#include "dbus-sysdeps-unix.h"
29
#include "dbus-internals.h"
30
#include "dbus-test.h"
31
#include "dbus-protocol.h"
32 33 34 35 36

#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
37
#include <stdlib.h>
38 39 40
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
41
#ifdef HAVE_SYSTEMD
42 43 44
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
45 46
#include <systemd/sd-journal.h>
#endif
47

48 49
extern char **environ;

50 51 52 53 54
/**
 * @addtogroup DBusInternalsUtils
 * @{
 */

55 56 57 58 59
/*
 * I'm pretty sure this whole spawn file could be made simpler,
 * if you thought about it a bit.
 */

60 61 62
/**
 * Enumeration for status of a read()
 */
63 64
typedef enum
{
65 66 67
  READ_STATUS_OK,    /**< Read succeeded */
  READ_STATUS_ERROR, /**< Some kind of error */
  READ_STATUS_EOF    /**< EOF returned */
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
} ReadStatus;

static ReadStatus
read_ints (int        fd,
	   int       *buf,
	   int        n_ints_in_buf,
	   int       *n_ints_read,
	   DBusError *error)
{
  size_t bytes = 0;    
  ReadStatus retval;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  retval = READ_STATUS_OK;
  
  while (TRUE)
    {
86 87
      ssize_t chunk;
      size_t to_read;
88 89 90 91 92

      to_read = sizeof (int) * n_ints_in_buf - bytes;

      if (to_read == 0)
        break;
93 94

    again:
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
      
      chunk = read (fd,
                    ((char*)buf) + bytes,
                    to_read);
      
      if (chunk < 0 && errno == EINTR)
        goto again;
          
      if (chunk < 0)
        {
          dbus_set_error (error,
			  DBUS_ERROR_SPAWN_FAILED,
			  "Failed to read from child pipe (%s)",
			  _dbus_strerror (errno));

          retval = READ_STATUS_ERROR;
          break;
        }
      else if (chunk == 0)
        {
          retval = READ_STATUS_EOF;
          break; /* EOF */
        }
      else /* chunk > 0 */
	bytes += chunk;
    }

  *n_ints_read = (int)(bytes / sizeof(int));

  return retval;
}

static ReadStatus
read_pid (int        fd,
          pid_t     *buf,
          DBusError *error)
{
  size_t bytes = 0;    
  ReadStatus retval;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  retval = READ_STATUS_OK;
  
  while (TRUE)
    {
141 142 143
      ssize_t chunk;
      size_t to_read;

144 145 146 147
      to_read = sizeof (pid_t) - bytes;

      if (to_read == 0)
        break;
148 149

    again:
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
      
      chunk = read (fd,
                    ((char*)buf) + bytes,
                    to_read);
      if (chunk < 0 && errno == EINTR)
        goto again;
          
      if (chunk < 0)
        {
          dbus_set_error (error,
			  DBUS_ERROR_SPAWN_FAILED,
			  "Failed to read from child pipe (%s)",
			  _dbus_strerror (errno));

          retval = READ_STATUS_ERROR;
          break;
        }
      else if (chunk == 0)
        {
          retval = READ_STATUS_EOF;
          break; /* EOF */
        }
      else /* chunk > 0 */
	bytes += chunk;
    }

  return retval;
}

/* The implementation uses an intermediate child between the main process
 * and the grandchild. The grandchild is our spawned process. The intermediate
 * child is a babysitter process; it keeps track of when the grandchild
 * exits/crashes, and reaps the grandchild.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
 *
 * We automatically reap the babysitter process, killing it if necessary,
 * when the DBusBabysitter's refcount goes to zero.
 *
 * Processes:
 *
 * main process
 * | fork() A
 * \- babysitter
 *    | fork () B
 *    \- grandchild     --> exec -->    spawned process
 *
 * IPC:
 *                  child_err_report_pipe
 *          /-----------<---------<--------------\
 *          |                                    ^
 *          v                                    |
 * main process           babysitter          grandchild
 *          ^                 ^
 *          v                 v
 *          \-------<->-------/
 *            babysitter_pipe
 *
 * child_err_report_pipe is genuinely a pipe.
 * The READ_END (also called error_pipe_from_child) is used in the main
 * process. The WRITE_END (also called child_err_report_fd) is used in
 * the grandchild process.
 *
 * On failure, the grandchild process sends CHILD_EXEC_FAILED + errno.
 * On success, the pipe just closes (because it's close-on-exec) without
 * sending any bytes.
 *
 * babysitter_pipe is mis-named: it's really a bidirectional socketpair.
 * The [0] end (also called socket_to_babysitter) is used in the main
 * process, the [1] end (also called parent_pipe) is used in the babysitter.
 *
 * If the fork() labelled B in the diagram above fails, the babysitter sends
 * CHILD_FORK_FAILED + errno.
 * On success, the babysitter sends CHILD_PID + the grandchild's pid.
 * On SIGCHLD, the babysitter sends CHILD_EXITED + the exit status.
 * The main process doesn't explicitly send anything, but when it exits,
 * the babysitter gets POLLHUP or POLLERR.
225 226 227 228 229 230 231 232 233 234 235
 */

/* Messages from children to parents */
enum
{
  CHILD_EXITED,            /* This message is followed by the exit status int */
  CHILD_FORK_FAILED,       /* Followed by errno */
  CHILD_EXEC_FAILED,       /* Followed by errno */
  CHILD_PID                /* Followed by pid_t */
};

236 237 238
/**
 * Babysitter implementation details
 */
239 240
struct DBusBabysitter
{
241
  int refcount; /**< Reference count */
242

243 244
  char *log_name; /**< the name under which to log messages about this
		    process being spawned */
245
  
246
  DBusSocket socket_to_babysitter; /**< Connection to the babysitter process */
247
  int error_pipe_from_child; /**< Connection to the process that does the exec() */
248
  
249 250
  pid_t sitter_pid;  /**< PID Of the babysitter */
  pid_t grandchild_pid; /**< PID of the grandchild */
251

252
  DBusWatchList *watches; /**< Watches */
253

254 255
  DBusWatch *error_watch; /**< Error pipe watch */
  DBusWatch *sitter_watch; /**< Sitter pipe watch */
256

257 258 259
  DBusBabysitterFinishedFunc finished_cb;
  void *finished_data;

260 261 262 263 264
  int errnum; /**< Error number */
  int status; /**< Exit status code */
  unsigned int have_child_status : 1; /**< True if child status has been reaped */
  unsigned int have_fork_errnum : 1; /**< True if we have an error code from fork() */
  unsigned int have_exec_errnum : 1; /**< True if we have an error code from exec() */
265 266 267 268 269 270 271 272 273 274 275 276 277
};

static DBusBabysitter*
_dbus_babysitter_new (void)
{
  DBusBabysitter *sitter;

  sitter = dbus_new0 (DBusBabysitter, 1);
  if (sitter == NULL)
    return NULL;

  sitter->refcount = 1;

278
  sitter->socket_to_babysitter.fd = -1;
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
  sitter->error_pipe_from_child = -1;
  
  sitter->sitter_pid = -1;
  sitter->grandchild_pid = -1;

  sitter->watches = _dbus_watch_list_new ();
  if (sitter->watches == NULL)
    goto failed;
  
  return sitter;

 failed:
  _dbus_babysitter_unref (sitter);
  return NULL;
}

/**
 * Increment the reference count on the babysitter object.
 *
 * @param sitter the babysitter
299
 * @returns the babysitter
300
 */
301
DBusBabysitter *
302 303 304 305 306 307
_dbus_babysitter_ref (DBusBabysitter *sitter)
{
  _dbus_assert (sitter != NULL);
  _dbus_assert (sitter->refcount > 0);
  
  sitter->refcount += 1;
308 309

  return sitter;
310 311
}

312 313 314
static void close_socket_to_babysitter  (DBusBabysitter *sitter);
static void close_error_pipe_from_child (DBusBabysitter *sitter);

315 316
/**
 * Decrement the reference count on the babysitter object.
317 318 319
 * When the reference count of the babysitter object reaches
 * zero, the babysitter is killed and the child that was being
 * babysat gets emancipated.
320 321 322 323 324 325 326 327 328 329 330
 *
 * @param sitter the babysitter
 */
void
_dbus_babysitter_unref (DBusBabysitter *sitter)
{
  _dbus_assert (sitter != NULL);
  _dbus_assert (sitter->refcount > 0);
  
  sitter->refcount -= 1;
  if (sitter->refcount == 0)
331 332 333 334 335 336 337 338 339
    {
      /* If we haven't forked other babysitters
       * since this babysitter and socket were
       * created then this close will cause the
       * babysitter to wake up from poll with
       * a hangup and then the babysitter will
       * quit itself.
       */
      close_socket_to_babysitter (sitter);
340

341
      close_error_pipe_from_child (sitter);
342

343
      if (sitter->sitter_pid > 0)
344 345 346 347
        {
          int status;
          int ret;

348 349 350 351 352 353 354 355 356 357 358 359 360
          /* It's possible the babysitter died on its own above 
           * from the close, or was killed randomly
           * by some other process, so first try to reap it
           */
          ret = waitpid (sitter->sitter_pid, &status, WNOHANG);

          /* If we couldn't reap the child then kill it, and
           * try again
           */
          if (ret == 0)
            kill (sitter->sitter_pid, SIGKILL);

          if (ret == 0)
361 362 363 364 365 366 367
            {
              do
                {
                  ret = waitpid (sitter->sitter_pid, &status, 0);
                }
              while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
            }
368

369 370
          if (ret < 0)
            {
371
              if (errno == ECHILD)
372 373 374 375 376 377 378
                _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
              else
                _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
                            errno, _dbus_strerror (errno));
            }
          else
            {
379 380 381
              _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
                             (long) ret, (long) sitter->sitter_pid);
              
382 383 384 385 386 387 388 389 390
              if (WIFEXITED (sitter->status))
                _dbus_verbose ("Babysitter exited with status %d\n",
                               WEXITSTATUS (sitter->status));
              else if (WIFSIGNALED (sitter->status))
                _dbus_verbose ("Babysitter received signal %d\n",
                               WTERMSIG (sitter->status));
              else
                _dbus_verbose ("Babysitter exited abnormally\n");
            }
391 392

          sitter->sitter_pid = -1;
393 394 395 396 397
        }

      if (sitter->watches)
        _dbus_watch_list_free (sitter->watches);

398
      dbus_free (sitter->log_name);
399 400 401 402 403 404 405 406 407 408 409
      
      dbus_free (sitter);
    }
}

static ReadStatus
read_data (DBusBabysitter *sitter,
           int             fd)
{
  int what;
  int got;
410
  DBusError error = DBUS_ERROR_INIT;
411
  ReadStatus r;
412

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
  r = read_ints (fd, &what, 1, &got, &error);

  switch (r)
    {
    case READ_STATUS_ERROR:
      _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
      dbus_error_free (&error);
      return r;

    case READ_STATUS_EOF:
      return r;

    case READ_STATUS_OK:
      break;
    }
  
  if (got == 1)
    {
      switch (what)
        {
        case CHILD_EXITED:
        case CHILD_FORK_FAILED:
        case CHILD_EXEC_FAILED:
          {
            int arg;
            
            r = read_ints (fd, &arg, 1, &got, &error);

            switch (r)
              {
              case READ_STATUS_ERROR:
                _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
                dbus_error_free (&error);
                return r;
              case READ_STATUS_EOF:
                return r;
              case READ_STATUS_OK:
                break;
              }
            
            if (got == 1)
              {
                if (what == CHILD_EXITED)
                  {
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
                    /* Do not reset sitter->errnum to 0 here. We get here if
                     * the babysitter reports that the grandchild process has
                     * exited, and there are two ways that can happen:
                     *
                     * 1. grandchild successfully exec()s the desired process,
                     * but then the desired process exits or is terminated
                     * by a signal. The babysitter observes this and reports
                     * CHILD_EXITED.
                     *
                     * 2. grandchild fails to exec() the desired process,
                     * attempts to report the exec() failure (which
                     * we will receive as CHILD_EXEC_FAILED), and then
                     * exits itself (which will prompt the babysitter to
                     * send CHILD_EXITED). We want the CHILD_EXEC_FAILED
                     * to take precedence (and have its errno logged),
                     * which _dbus_babysitter_set_child_exit_error() does.
                     */
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
                    sitter->have_child_status = TRUE;
                    sitter->status = arg;
                    _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
                                   WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
                                   WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
                  }
                else if (what == CHILD_FORK_FAILED)
                  {
                    sitter->have_fork_errnum = TRUE;
                    sitter->errnum = arg;
                    _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
                  }
                else if (what == CHILD_EXEC_FAILED)
                  {
                    sitter->have_exec_errnum = TRUE;
                    sitter->errnum = arg;
                    _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
                  }
              }
          }
          break;
        case CHILD_PID:
          {
            pid_t pid = -1;

            r = read_pid (fd, &pid, &error);
            
            switch (r)
              {
              case READ_STATUS_ERROR:
                _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
                dbus_error_free (&error);
                return r;
              case READ_STATUS_EOF:
                return r;
              case READ_STATUS_OK:
                break;
              }
            
            sitter->grandchild_pid = pid;
            
            _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
          }
          break;
        default:
          _dbus_warn ("Unknown message received from babysitter process\n");
          break;
        }
    }

  return r;
}

static void
close_socket_to_babysitter (DBusBabysitter *sitter)
{
  _dbus_verbose ("Closing babysitter\n");
531 532 533 534 535 536 537 538 539 540

  if (sitter->sitter_watch != NULL)
    {
      _dbus_assert (sitter->watches != NULL);
      _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
      _dbus_watch_invalidate (sitter->sitter_watch);
      _dbus_watch_unref (sitter->sitter_watch);
      sitter->sitter_watch = NULL;
    }

541
  if (sitter->socket_to_babysitter.fd >= 0)
542 543
    {
      _dbus_close_socket (sitter->socket_to_babysitter, NULL);
544
      sitter->socket_to_babysitter.fd = -1;
545
    }
546 547 548 549 550 551
}

static void
close_error_pipe_from_child (DBusBabysitter *sitter)
{
  _dbus_verbose ("Closing child error\n");
552 553 554 555 556 557 558 559 560 561 562 563

  if (sitter->error_watch != NULL)
    {
      _dbus_assert (sitter->watches != NULL);
      _dbus_watch_list_remove_watch (sitter->watches,  sitter->error_watch);
      _dbus_watch_invalidate (sitter->error_watch);
      _dbus_watch_unref (sitter->error_watch);
      sitter->error_watch = NULL;
    }

  if (sitter->error_pipe_from_child >= 0)
    {
564
      _dbus_close (sitter->error_pipe_from_child, NULL);
565 566
      sitter->error_pipe_from_child = -1;
    }
567 568 569 570 571 572 573 574 575 576 577 578 579
}

static void
handle_babysitter_socket (DBusBabysitter *sitter,
                          int             revents)
{
  /* Even if we have POLLHUP, we want to keep reading
   * data until POLLIN goes away; so this function only
   * looks at HUP/ERR if no IN is set.
   */
  if (revents & _DBUS_POLLIN)
    {
      _dbus_verbose ("Reading data from babysitter\n");
580
      if (read_data (sitter, sitter->socket_to_babysitter.fd) != READ_STATUS_OK)
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
        close_socket_to_babysitter (sitter);
    }
  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
    {
      close_socket_to_babysitter (sitter);
    }
}

static void
handle_error_pipe (DBusBabysitter *sitter,
                   int             revents)
{
  if (revents & _DBUS_POLLIN)
    {
      _dbus_verbose ("Reading data from child error\n");
      if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
        close_error_pipe_from_child (sitter);
    }
  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
    {
      close_error_pipe_from_child (sitter);
    }
}

/* returns whether there were any poll events handled */
static dbus_bool_t
babysitter_iteration (DBusBabysitter *sitter,
                      dbus_bool_t     block)
{
  DBusPollFD fds[2];
  int i;
  dbus_bool_t descriptors_ready;

  descriptors_ready = FALSE;
  
  i = 0;

  if (sitter->error_pipe_from_child >= 0)
    {
      fds[i].fd = sitter->error_pipe_from_child;
      fds[i].events = _DBUS_POLLIN;
      fds[i].revents = 0;
      ++i;
    }
  
626
  if (sitter->socket_to_babysitter.fd >= 0)
627
    {
628
      fds[i].fd = sitter->socket_to_babysitter.fd;
629 630 631 632 633 634 635 636 637
      fds[i].events = _DBUS_POLLIN;
      fds[i].revents = 0;
      ++i;
    }

  if (i > 0)
    {
      int ret;

638 639 640 641 642 643
      do
        {
          ret = _dbus_poll (fds, i, 0);
        }
      while (ret < 0 && errno == EINTR);

644
      if (ret == 0 && block)
645 646 647 648 649 650 651 652
        {
          do
            {
              ret = _dbus_poll (fds, i, -1);
            }
          while (ret < 0 && errno == EINTR);
        }

653 654 655 656 657 658 659 660 661
      if (ret > 0)
        {
          descriptors_ready = TRUE;
          
          while (i > 0)
            {
              --i;
              if (fds[i].fd == sitter->error_pipe_from_child)
                handle_error_pipe (sitter, fds[i].revents);
662
              else if (fds[i].fd == sitter->socket_to_babysitter.fd)
663 664 665 666 667 668 669 670 671 672 673 674
                handle_babysitter_socket (sitter, fds[i].revents);
            }
        }
    }

  return descriptors_ready;
}

/**
 * Macro returns #TRUE if the babysitter still has live sockets open to the
 * babysitter child or the grandchild.
 */
675
#define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter.fd >= 0 || (sitter)->error_pipe_from_child >= 0)
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690

/**
 * Blocks until the babysitter process gives us the PID of the spawned grandchild,
 * then kills the spawned grandchild.
 *
 * @param sitter the babysitter object
 */
void
_dbus_babysitter_kill_child (DBusBabysitter *sitter)
{
  /* be sure we have the PID of the child */
  while (LIVE_CHILDREN (sitter) &&
         sitter->grandchild_pid == -1)
    babysitter_iteration (sitter, TRUE);

691 692 693
  _dbus_verbose ("Got child PID %ld for killing\n",
                 (long) sitter->grandchild_pid);
  
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
  if (sitter->grandchild_pid == -1)
    return; /* child is already dead, or we're so hosed we'll never recover */

  kill (sitter->grandchild_pid, SIGKILL);
}

/**
 * Checks whether the child has exited, without blocking.
 *
 * @param sitter the babysitter
 */
dbus_bool_t
_dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
{

  /* Be sure we're up-to-date */
  while (LIVE_CHILDREN (sitter) &&
         babysitter_iteration (sitter, FALSE))
    ;

  /* We will have exited the babysitter when the child has exited */
715
  return sitter->socket_to_babysitter.fd < 0;
716 717
}

718
/**
719 720 721 722 723 724
 * Gets the exit status of the child. We do this so implementation specific
 * detail is not cluttering up dbus, for example the system launcher code.
 * This can only be called if the child has exited, i.e. call
 * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
 * did not return a status code, e.g. because the child was signaled
 * or we failed to ever launch the child in the first place.
725 726 727 728 729 730
 *
 * @param sitter the babysitter
 * @param status the returned status code
 * @returns #FALSE on failure
 */
dbus_bool_t
731 732
_dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
                                        int            *status)
733 734 735
{
  if (!_dbus_babysitter_get_child_exited (sitter))
    _dbus_assert_not_reached ("Child has not exited");
736 737 738 739
  
  if (!sitter->have_child_status ||
      !(WIFEXITED (sitter->status)))
    return FALSE;
740

741
  *status = WEXITSTATUS (sitter->status);
742 743 744
  return TRUE;
}

745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
/**
 * Sets the #DBusError with an explanation of why the spawned
 * child process exited (on a signal, or whatever). If
 * the child process has not exited, does nothing (error
 * will remain unset).
 *
 * @param sitter the babysitter
 * @param error an error to fill in
 */
void
_dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
                                       DBusError      *error)
{
  if (!_dbus_babysitter_get_child_exited (sitter))
    return;

  /* Note that if exec fails, we will also get a child status
   * from the babysitter saying the child exited,
   * so we need to give priority to the exec error
   */
  if (sitter->have_exec_errnum)
    {
      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
                      "Failed to execute program %s: %s",
769
                      sitter->log_name, _dbus_strerror (sitter->errnum));
770 771 772 773 774
    }
  else if (sitter->have_fork_errnum)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
                      "Failed to fork a new process %s: %s",
775
                      sitter->log_name, _dbus_strerror (sitter->errnum));
776 777 778 779 780 781
    }
  else if (sitter->have_child_status)
    {
      if (WIFEXITED (sitter->status))
        dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
                        "Process %s exited with status %d",
782
                        sitter->log_name, WEXITSTATUS (sitter->status));
783 784 785
      else if (WIFSIGNALED (sitter->status))
        dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
                        "Process %s received signal %d",
786
                        sitter->log_name, WTERMSIG (sitter->status));
787 788 789
      else
        dbus_set_error (error, DBUS_ERROR_FAILED,
                        "Process %s exited abnormally",
790
                        sitter->log_name);
791 792 793 794 795
    }
  else
    {
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "Process %s exited, reason unknown",
796
                      sitter->log_name);
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
    }
}

/**
 * Sets watch functions to notify us when the
 * babysitter object needs to read/write file descriptors.
 *
 * @param sitter the babysitter
 * @param add_function function to begin monitoring a new descriptor.
 * @param remove_function function to stop monitoring a descriptor.
 * @param toggled_function function to notify when the watch is enabled/disabled
 * @param data data to pass to add_function and remove_function.
 * @param free_data_function function to be called to free the data.
 * @returns #FALSE on failure (no memory)
 */
dbus_bool_t
_dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
                                      DBusAddWatchFunction       add_function,
                                      DBusRemoveWatchFunction    remove_function,
                                      DBusWatchToggledFunction   toggled_function,
                                      void                      *data,
                                      DBusFreeFunction           free_data_function)
{
  return _dbus_watch_list_set_functions (sitter->watches,
                                         add_function,
                                         remove_function,
                                         toggled_function,
                                         data,
                                         free_data_function);
}

828 829 830 831
static dbus_bool_t
handle_watch (DBusWatch       *watch,
              unsigned int     condition,
              void            *data)
832
{
833
  DBusBabysitter *sitter = _dbus_babysitter_ref (data);
834 835 836 837 838 839 840 841 842 843 844
  int revents;
  int fd;
  
  revents = 0;
  if (condition & DBUS_WATCH_READABLE)
    revents |= _DBUS_POLLIN;
  if (condition & DBUS_WATCH_ERROR)
    revents |= _DBUS_POLLERR;
  if (condition & DBUS_WATCH_HANGUP)
    revents |= _DBUS_POLLHUP;

845
  fd = dbus_watch_get_socket (watch);
846 847 848

  if (fd == sitter->error_pipe_from_child)
    handle_error_pipe (sitter, revents);
849
  else if (fd == sitter->socket_to_babysitter.fd)
850
    handle_babysitter_socket (sitter, revents);
851 852 853 854

  while (LIVE_CHILDREN (sitter) &&
         babysitter_iteration (sitter, FALSE))
    ;
855

856 857
  /* fd.o #32992: if the handle_* methods closed their sockets, they previously
   * didn't always remove the watches. Check that we don't regress. */
858
  _dbus_assert (sitter->socket_to_babysitter.fd != -1 || sitter->sitter_watch == NULL);
859
  _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
860

861 862 863 864 865 866 867
  if (_dbus_babysitter_get_child_exited (sitter) &&
      sitter->finished_cb != NULL)
    {
      sitter->finished_cb (sitter, sitter->finished_data);
      sitter->finished_cb = NULL;
    }

868
  _dbus_babysitter_unref (sitter);
869 870 871
  return TRUE;
}

872
/** Helps remember which end of the pipe is which */
873
#define READ_END 0
874
/** Helps remember which end of the pipe is which */
875 876 877
#define WRITE_END 1


878 879 880 881 882 883 884 885
/* Avoids a danger in re-entrant situations (calling close()
 * on a file descriptor twice, and another module has
 * re-opened it since the first close).
 *
 * This previously claimed to be relevant for threaded situations, but by
 * trivial inspection, it is not thread-safe. It doesn't actually
 * matter, since this module is only used in the -util variant of the
 * library, which is only used in single-threaded situations.
886 887 888 889 890 891 892 893 894 895
 */
static int
close_and_invalidate (int *fd)
{
  int ret;

  if (*fd < 0)
    return -1;
  else
    {
896
      ret = _dbus_close (*fd, NULL);
897 898 899 900 901 902 903
      *fd = -1;
    }

  return ret;
}

static dbus_bool_t
904 905
make_pipe (int         p[2],
           DBusError  *error)
906
{
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
  int retval;

#ifdef HAVE_PIPE2
  dbus_bool_t cloexec_done;

  retval = pipe2 (p, O_CLOEXEC);
  cloexec_done = retval >= 0;

  /* Check if kernel seems to be too old to know pipe2(). We assume
     that if pipe2 is available, O_CLOEXEC is too.  */
  if (retval < 0 && errno == ENOSYS)
#endif
    {
      retval = pipe(p);
    }

923
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
924 925

  if (retval < 0)
926 927 928 929
    {
      dbus_set_error (error,
		      DBUS_ERROR_SPAWN_FAILED,
		      "Failed to create pipe for communicating with child process (%s)",
930
		      _dbus_strerror (errno));
931 932
      return FALSE;
    }
933

934 935 936 937 938 939 940 941
#ifdef HAVE_PIPE2
  if (!cloexec_done)
#endif
    {
      _dbus_fd_set_close_on_exec (p[0]);
      _dbus_fd_set_close_on_exec (p[1]);
    }

942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
  return TRUE;
}

static void
do_write (int fd, const void *buf, size_t count)
{
  size_t bytes_written;
  int ret;
  
  bytes_written = 0;
  
 again:
  
  ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);

  if (ret < 0)
    {
      if (errno == EINTR)
        goto again;
      else
        {
          _dbus_warn ("Failed to write data to pipe!\n");
964
          exit (1); /* give up, we suck */
965 966
        }
    }
967
  else
968 969 970 971
    bytes_written += ret;
  
  if (bytes_written < count)
    goto again;
972 973 974 975 976 977
}

static void
write_err_and_exit (int fd, int msg)
{
  int en = errno;
978 979 980

  do_write (fd, &msg, sizeof (msg));
  do_write (fd, &en, sizeof (en));
981
  
982
  exit (1);
983 984
}

985 986
static void
write_pid (int fd, pid_t pid)
987
{
988
  int msg = CHILD_PID;
989
  
990 991 992
  do_write (fd, &msg, sizeof (msg));
  do_write (fd, &pid, sizeof (pid));
}
993

994 995 996 997 998 999 1000 1001
static void
write_status_and_exit (int fd, int status)
{
  int msg = CHILD_EXITED;
  
  do_write (fd, &msg, sizeof (msg));
  do_write (fd, &status, sizeof (status));
  
1002
  exit (0);
1003 1004 1005 1006 1007
}

static void
do_exec (int                       child_err_report_fd,
	 char                    **argv,
1008
	 char                    **envp,
1009 1010 1011
	 DBusSpawnChildSetupFunc   child_setup,
	 void                     *user_data)
{
1012
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
1013 1014 1015
  int i, max_open;
#endif

1016
  _dbus_verbose_reset ();
1017
  _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
1018 1019
                 _dbus_getpid ());
  
1020 1021 1022
  if (child_setup)
    (* child_setup) (user_data);

1023
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
1024 1025 1026 1027 1028 1029
  max_open = sysconf (_SC_OPEN_MAX);
  
  for (i = 3; i < max_open; i++)
    {
      int retval;

1030 1031 1032
      if (i == child_err_report_fd)
        continue;
      
1033 1034 1035
      retval = fcntl (i, F_GETFD);

      if (retval != -1 && !(retval & FD_CLOEXEC))
1036
        _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
1037 1038
    }
#endif
1039 1040 1041 1042 1043 1044 1045

  if (envp == NULL)
    {
      _dbus_assert (environ != NULL);

      envp = environ;
    }
1046
  
1047
  execve (argv[0], argv, envp);
1048
  
1049 1050 1051
  /* Exec failed */
  write_err_and_exit (child_err_report_fd,
                      CHILD_EXEC_FAILED);
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
}

static void
check_babysit_events (pid_t grandchild_pid,
                      int   parent_pipe,
                      int   revents)
{
  pid_t ret;
  int status;
  
1062 1063 1064
  do
    {
      ret = waitpid (grandchild_pid, &status, WNOHANG);
1065 1066 1067
      /* The man page says EINTR can't happen with WNOHANG,
       * but there are reports of it (maybe only with valgrind?)
       */
1068 1069
    }
  while (ret < 0 && errno == EINTR);
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081

  if (ret == 0)
    {
      _dbus_verbose ("no child exited\n");
      
      ; /* no child exited */
    }
  else if (ret < 0)
    {
      /* This isn't supposed to happen. */
      _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
                  _dbus_strerror (errno));
1082
      exit (1);
1083 1084 1085 1086
    }
  else if (ret == grandchild_pid)
    {
      /* Child exited */
1087 1088
      _dbus_verbose ("reaped child pid %ld\n", (long) ret);
      
1089 1090 1091 1092 1093 1094
      write_status_and_exit (parent_pipe, status);
    }
  else
    {
      _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
                  (int) ret);
1095
      exit (1);
1096 1097 1098 1099
    }

  if (revents & _DBUS_POLLIN)
    {
1100
      _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
1101 1102 1103 1104 1105
    }

  if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
    {
      /* Parent is gone, so we just exit */
1106
      _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
1107
      exit (0);
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
    }
}

static int babysit_sigchld_pipe = -1;

static void
babysit_signal_handler (int signo)
{
  char b = '\0';
 again:
1118 1119 1120
  if (write (babysit_sigchld_pipe, &b, 1) <= 0) 
    if (errno == EINTR)
      goto again;
1121 1122 1123 1124 1125
}

static void
babysit (pid_t grandchild_pid,
         int   parent_pipe)
1126
{
1127 1128
  int sigchld_pipe[2];

1129 1130 1131 1132 1133
  /* We don't exec, so we keep parent state, such as the pid that
   * _dbus_verbose() uses. Reset the pid here.
   */
  _dbus_verbose_reset ();
  
1134 1135 1136 1137 1138 1139 1140 1141
  /* I thought SIGCHLD would just wake up the poll, but
   * that didn't seem to work, so added this pipe.
   * Probably the pipe is more likely to work on busted
   * operating systems anyhow.
   */
  if (pipe (sigchld_pipe) < 0)
    {
      _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
1142
      exit (1);
1143 1144 1145
    }

  babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
1146 1147

  _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
  
  write_pid (parent_pipe, grandchild_pid);

  check_babysit_events (grandchild_pid, parent_pipe, 0);

  while (TRUE)
    {
      DBusPollFD pfds[2];
      
      pfds[0].fd = parent_pipe;
      pfds[0].events = _DBUS_POLLIN;
      pfds[0].revents = 0;

      pfds[1].fd = sigchld_pipe[READ_END];
      pfds[1].events = _DBUS_POLLIN;
      pfds[1].revents = 0;
      
1165 1166 1167 1168 1169
      if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
        {
          _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
          exit (1);
        }
1170 1171 1172 1173 1174 1175 1176 1177

      if (pfds[0].revents != 0)
        {
          check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
        }
      else if (pfds[1].revents & _DBUS_POLLIN)
        {
          char b;
1178
          if (read (sigchld_pipe[READ_END], &b, 1) == -1)
1179 1180 1181
            {
              /* ignore */
            }
1182 1183 1184 1185
          /* do waitpid check */
          check_babysit_events (grandchild_pid, parent_pipe, 0);
        }
    }
1186
  
1187
  exit (1);
1188 1189 1190
}

/**
1191
 * Spawns a new process. The child_setup
1192 1193 1194
 * function is passed the given user_data and is run in the child
 * just before calling exec().
 *
1195 1196 1197 1198
 * Also creates a "babysitter" which tracks the status of the
 * child process, advising the parent if the child exits.
 * If the spawn fails, no babysitter is created.
 * If sitter_p is #NULL, no babysitter is kept.
1199
 *
1200
 * @param sitter_p return location for babysitter or #NULL
1201
 * @param log_name the name under which to log messages about this process being spawned
1202
 * @param argv the executable and arguments
1203
 * @param env the environment, or #NULL to copy the parent's
1204 1205 1206 1207 1208 1209
 * @param child_setup function to call in child pre-exec()
 * @param user_data user data for setup function
 * @param error error object to be filled in if function fails
 * @returns #TRUE on success, #FALSE if error is filled in
 */
dbus_bool_t
1210
_dbus_spawn_async_with_babysitter (DBusBabysitter          **sitter_p,
1211
                                   const char               *log_name,
1212
                                   char                    **argv,
1213
                                   char                    **env,
1214 1215 1216
                                   DBusSpawnChildSetupFunc   child_setup,
                                   void                     *user_data,
                                   DBusError                *error)
1217
{
1218
  DBusBabysitter *sitter;
1219
  int child_err_report_pipe[2] = { -1, -1 };
1220
  DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT };
1221
  pid_t pid;
1222 1223 1224 1225
#ifdef HAVE_SYSTEMD
  int fd_out = -1;
  int fd_err = -1;
#endif
1226
  
1227
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1228
  _dbus_assert (argv[0] != NULL);
1229

1230 1231 1232
  if (sitter_p != NULL)
    *sitter_p = NULL;

1233 1234 1235 1236 1237 1238 1239 1240 1241
  sitter = NULL;

  sitter = _dbus_babysitter_new ();
  if (sitter == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return FALSE;
    }

1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252
  sitter->log_name = _dbus_strdup (log_name);
  if (sitter->log_name == NULL && log_name != NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto cleanup_and_fail;
    }

  if (sitter->log_name == NULL)
    sitter->log_name = _dbus_strdup (argv[0]);

  if (sitter->log_name == NULL)
1253 1254 1255 1256
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto cleanup_and_fail;
    }
1257 1258
  
  if (!make_pipe (child_err_report_pipe, error))
1259 1260
    goto cleanup_and_fail;

1261
  if (!_dbus_socketpair (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
1262
    goto cleanup_and_fail;
1263

1264 1265 1266 1267 1268 1269 1270
  /* Setting up the babysitter is only useful in the parent,
   * but we don't want to run out of memory and fail
   * after we've already forked, since then we'd leak
   * child processes everywhere.
   */
  sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
                                         DBUS_WATCH_READABLE,
1271
                                         TRUE, handle_watch, sitter, NULL);
1272 1273 1274 1275 1276 1277 1278 1279
  if (sitter->error_watch == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto cleanup_and_fail;
    }
        
  if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->error_watch))
    {
1280 1281 1282 1283 1284 1285
      /* we need to free it early so the destructor won't try to remove it
       * without it having been added, which DBusLoop doesn't allow */
      _dbus_watch_invalidate (sitter->error_watch);
      _dbus_watch_unref (sitter->error_watch);
      sitter->error_watch = NULL;

1286 1287 1288 1289
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto cleanup_and_fail;
    }
      
1290
  sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0].fd,
1291
                                          DBUS_WATCH_READABLE,
1292
                                          TRUE, handle_watch, sitter, NULL);
1293 1294 1295 1296 1297 1298 1299 1300
  if (sitter->sitter_watch == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto cleanup_and_fail;
    }
      
  if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
    {
1301 1302 1303 1304 1305 1306
      /* we need to free it early so the destructor won't try to remove it
       * without it having been added, which DBusLoop doesn't allow */
      _dbus_watch_invalidate (sitter->sitter_watch);
      _dbus_watch_unref (sitter->sitter_watch);
      sitter->sitter_watch = NULL;

1307 1308 1309 1310 1311
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      goto cleanup_and_fail;
    }

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1312 1313

#ifdef HAVE_SYSTEMD
1314 1315 1316 1317
  /* This may fail, but it's not critical.
   * In particular, if we were compiled with journald support but are now
   * running on a non-systemd system, this is going to fail, so we
   * have to cope gracefully. */
1318 1319 1320 1321
  fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
  fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
#endif

1322 1323 1324 1325 1326 1327 1328
  pid = fork ();
  
  if (pid < 0)
    {
      dbus_set_error (error,
		      DBUS_ERROR_SPAWN_FORK_FAILED,
		      "Failed to fork (%s)",
1329 1330
		      _dbus_strerror (errno));
      goto cleanup_and_fail;
1331 1332 1333
    }
  else if (pid == 0)
    {
1334 1335
      /* Immediate child, this is the babysitter process. */
      int grandchild_pid;
1336 1337 1338 1339 1340 1341
      
      /* Be sure we crash if the parent exits
       * and we write to the err_report_pipe
       */
      signal (SIGPIPE, SIG_DFL);

1342 1343
      /* Close the parent's end of the pipes. */
      close_and_invalidate (&child_err_report_pipe[READ_END]);
1344
      close_and_invalidate (&babysitter_pipe[0].fd);
1345 1346
      
      /* Create the child that will exec () */
1347 1348 1349 1350
      grandchild_pid = fork ();
      
      if (grandchild_pid < 0)
	{
1351
	  write_err_and_exit (babysitter_pipe[1].fd,
1352 1353
			      CHILD_FORK_FAILED);
          _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
1354 1355
	}
      else if (grandchild_pid == 0)
1356
      {
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
#ifdef __linux__
          int fd = -1;

#ifdef O_CLOEXEC
          fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
#endif

          if (fd < 0)
            {
              fd = open ("/proc/self/oom_score_adj", O_WRONLY);
              _dbus_fd_set_close_on_exec (fd);
            }

          if (fd >= 0)
            {
              if (write (fd, "0", sizeof (char)) < 0)
                _dbus_warn ("writing oom_score_adj error: %s\n", strerror (errno));
              _dbus_close (fd, NULL);
            }
#endif
1377
          /* Go back to ignoring SIGPIPE, since it's evil
1378
           */
1379 1380
          signal (SIGPIPE, SIG_IGN);

1381
          close_and_invalidate (&babysitter_pipe[1].fd);
1382
#ifdef HAVE_SYSTEMD
1383
	  /* log to systemd journal if possible */
1384 1385 1386 1387 1388 1389 1390
	  if (fd_out >= 0)
            dup2 (fd_out, STDOUT_FILENO);
	  if (fd_err >= 0)
            dup2 (fd_err, STDERR_FILENO);
          close_and_invalidate (&fd_out);
          close_and_invalidate (&fd_err);
#endif
1391
	  do_exec (child_err_report_pipe[WRITE_END],
1392
		   argv,
1393
		   env,
1394
		   child_setup, user_data);
1395
          _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
1396 1397 1398
	}
      else
	{
1399
          close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1400 1401 1402 1403
#ifdef HAVE_SYSTEMD
          close_and_invalidate (&fd_out);
          close_and_invalidate (&fd_err);
#endif
1404
          babysit (grandchild_pid, babysitter_pipe[1].fd);
1405
          _dbus_assert_not_reached ("Got to code after babysit()");
1406 1407 1408
	}
    }
  else
1409
    {      
1410
      /* Close the uncared-about ends of the pipes */
1411
      close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1412
      close_and_invalidate (&babysitter_pipe[1].fd);
1413 1414 1415 1416
#ifdef HAVE_SYSTEMD
      close_and_invalidate (&fd_out);
      close_and_invalidate (&fd_err);
#endif
1417

1418
      sitter->socket_to_babysitter = babysitter_pipe[0];
1419
      babysitter_pipe[0].fd = -1;
1420
      
1421 1422
      sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
      child_err_report_pipe[READ_END] = -1;
1423

1424
      sitter->sitter_pid = pid;
1425

1426 1427 1428 1429
      if (sitter_p != NULL)
        *sitter_p = sitter;
      else
        _dbus_babysitter_unref (sitter);
1430

1431 1432
      dbus_free_string_array (env);

1433 1434
      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
      
1435 1436 1437 1438 1439
      return TRUE;
    }

 cleanup_and_fail:

1440 1441 1442 1443
  _DBUS_ASSERT_ERROR_IS_SET (error);
  
  close_and_invalidate (&child_err_report_pipe[READ_END]);
  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1444 1445
  close_and_invalidate (&babysitter_pipe[0].fd);
  close_and_invalidate (&babysitter_pipe[1].fd);
1446 1447 1448 1449
#ifdef HAVE_SYSTEMD
  close_and_invalidate (&fd_out);
  close_and_invalidate (&fd_err);
#endif
1450 1451 1452 1453 1454 1455 1456

  if (sitter != NULL)
    _dbus_babysitter_unref (sitter);
  
  return FALSE;
}

1457 1458 1459 1460 1461 1462 1463 1464 1465
void
_dbus_babysitter_set_result_function  (DBusBabysitter             *sitter,
                                       DBusBabysitterFinishedFunc  finished,
                                       void                       *user_data)
{
  sitter->finished_cb = finished;
  sitter->finished_data = user_data;
}

1466 1467
/** @} */

1468
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
1469

1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
static char *
get_test_exec (const char *exe,
               DBusString *scratch_space)
{
  const char *dbus_test_exec;

  dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");

  if (dbus_test_exec == NULL)
    dbus_test_exec = DBUS_TEST_EXEC;

  if (!_dbus_string_init (scratch_space))
    return NULL;

  if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
                                   dbus_test_exec, exe, DBUS_EXEEXT))
    {
      _dbus_string_free (scratch_space);
      return NULL;
    }

  return _dbus_string_get_data (scratch_space);
}

1494 1495 1496 1497 1498 1499 1500
static void
_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
{
  while (LIVE_CHILDREN (sitter))
    babysitter_iteration (sitter, TRUE);
}

1501 1502 1503 1504
static dbus_bool_t
check_spawn_nonexistent (void *data)
{
  char *argv[4] = { NULL, NULL, NULL, NULL };
1505 1506
  DBusBabysitter *sitter = NULL;
  DBusError error = DBUS_ERROR_INIT;
1507 1508 1509 1510

  /*** Test launching nonexistent binary */
  
  argv[0] = "/this/does/not/exist/32542sdgafgafdg";
1511
  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv,
1512
                                         NULL, NULL, NULL,
1513
                                         &error))
1514
    {
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534
      _dbus_babysitter_block_for_child_exit (sitter);
      _dbus_babysitter_set_child_exit_error (sitter, &error);
    }

  if (sitter)
    _dbus_babysitter_unref (sitter);

  if (!dbus_error_is_set (&error))
    {
      _dbus_warn ("Did not get an error launching nonexistent executable\n");
      return FALSE;
    }

  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
    {
      _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
                  error.name, error.message);
      dbus_error_free (&error);
      return FALSE;
1535
    }
1536 1537 1538 1539 1540 1541 1542 1543 1544 1545

  dbus_error_free (&error);
  
  return TRUE;
}

static dbus_bool_t
check_spawn_segfault (void *data)
{
  char *argv[4] = { NULL, NULL, NULL, NULL };
1546 1547
  DBusBabysitter *sitter = NULL;
  DBusError error = DBUS_ERROR_INIT;
1548
  DBusString argv0;
1549

1550
  /*** Test launching segfault binary */
1551 1552 1553 1554 1555 1556 1557 1558 1559

  argv[0] = get_test_exec ("test-segfault", &argv0);

  if (argv[0] == NULL)
    {
      /* OOM was simulated, never mind */
      return TRUE;
    }

1560
  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
1561
                                         NULL, NULL, NULL,
1562 1563 1564 1565 1566 1567
                                         &error))
    {
      _dbus_babysitter_block_for_child_exit (sitter);
      _dbus_babysitter_set_child_exit_error (sitter, &error);
    }

1568 1569
  _dbus_string_free (&argv0);

1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
  if (sitter)
    _dbus_babysitter_unref (sitter);

  if (!dbus_error_is_set (&error))
    {
      _dbus_warn ("Did not get an error launching segfaulting binary\n");
      return FALSE;
    }

  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
    {
      _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
                  error.name, error.message);
      dbus_error_free (&error);
      return FALSE;
    }

  dbus_error_free (&error);
  
  return TRUE;
1591 1592
}

1593 1594 1595 1596
static dbus_bool_t
check_spawn_exit (void *data)
{
  char *argv[4] = { NULL, NULL, NULL, NULL };
1597 1598
  DBusBabysitter *sitter = NULL;
  DBusError error = DBUS_ERROR_INIT;
1599
  DBusString argv0;
1600 1601

  /*** Test launching exit failure binary */
1602 1603 1604 1605 1606 1607 1608 1609 1610

  argv[0] = get_test_exec ("test-exit", &argv0);

  if (argv[0] == NULL)
    {
      /* OOM was simulated, never mind */
      return TRUE;
    }

1611
  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
1612
                                         NULL, NULL, NULL,
1613 1614 1615 1616 1617 1618
                                         &error))
    {
      _dbus_babysitter_block_for_child_exit (sitter);
      _dbus_babysitter_set_child_exit_error (sitter, &error);
    }

1619 1620
  _dbus_string_free (&argv0);

1621 1622
  if (sitter)
    _dbus_babysitter_unref (sitter);
1623

1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
  if (!dbus_error_is_set (&error))
    {
      _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
      return FALSE;
    }

  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
    {
      _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
                  error.name, error.message);
      dbus_error_free (&error);
      return FALSE;
    }

  dbus_error_free (&error);
  
  return TRUE;
}

static dbus_bool_t
check_spawn_and_kill (void *data)
{
  char *argv[4] = { NULL, NULL, NULL, NULL };
1648 1649
  DBusBabysitter *sitter = NULL;
  DBusError error = DBUS_ERROR_INIT;
1650
  DBusString argv0;
1651 1652 1653

  /*** Test launching sleeping binary then killing it */

1654 1655 1656 1657 1658 1659 1660 1661
  argv[0] = get_test_exec ("test-sleep-forever", &argv0);

  if (argv[0] == NULL)
    {
      /* OOM was simulated, never mind */
      return TRUE;
    }

1662
  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
1663
                                         NULL, NULL, NULL,
1664 1665 1666 1667 1668 1669 1670 1671 1672
                                         &error))
    {
      _dbus_babysitter_kill_child (sitter);
      
      _dbus_babysitter_block_for_child_exit (sitter);
      
      _dbus_babysitter_set_child_exit_error (sitter, &error);
    }

1673 1674
  _dbus_string_free (&argv0);

1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723
  if (sitter)
    _dbus_babysitter_unref (sitter);

  if (!dbus_error_is_set (&error))
    {
      _dbus_warn ("Did not get an error after killing spawned binary\n");
      return FALSE;
    }

  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
    {
      _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
                  error.name, error.message);
      dbus_error_free (&error);
      return FALSE;
    }

  dbus_error_free (&error);
  
  return TRUE;
}

dbus_bool_t
_dbus_spawn_test (const char *test_data_dir)
{
  if (!_dbus_test_oom_handling ("spawn_nonexistent",
                                check_spawn_nonexistent,
                                NULL))
    return FALSE;

  if (!_dbus_test_oom_handling ("spawn_segfault",
                                check_spawn_segfault,
                                NULL))
    return FALSE;

  if (!_dbus_test_oom_handling ("spawn_exit",
                                check_spawn_exit,
                                NULL))
    return FALSE;

  if (!_dbus_test_oom_handling ("spawn_and_kill",
                                check_spawn_and_kill,
                                NULL))
    return FALSE;
  
  return TRUE;
}
#endif