Ticket #58099: patch-tiger-no-posix-spawn-2.diff

File patch-tiger-no-posix-spawn-2.diff, 5.2 KB (added by ballapete (Peter "Pete" Dyballa), 6 years ago)

Patchset for Ninja 1.9.0

  • src/subprocess-posix.cc

    old new  
    2323#include <stdio.h>
    2424#include <string.h>
    2525#include <sys/wait.h>
    26 #include <spawn.h>
    27 
    28 extern char** environ;
    2926
    3027#include "util.h"
    3128
     
    5451#endif  // !USE_PPOLL
    5552  SetCloseOnExec(fd_);
    5653
    57   posix_spawn_file_actions_t action;
    58   int err = posix_spawn_file_actions_init(&action);
    59   if (err != 0)
    60     Fatal("posix_spawn_file_actions_init: %s", strerror(err));
    61 
    62   err = posix_spawn_file_actions_addclose(&action, output_pipe[0]);
    63   if (err != 0)
    64     Fatal("posix_spawn_file_actions_addclose: %s", strerror(err));
    65 
    66   posix_spawnattr_t attr;
    67   err = posix_spawnattr_init(&attr);
    68   if (err != 0)
    69     Fatal("posix_spawnattr_init: %s", strerror(err));
    70 
    71   short flags = 0;
    72 
    73   flags |= POSIX_SPAWN_SETSIGMASK;
    74   err = posix_spawnattr_setsigmask(&attr, &set->old_mask_);
    75   if (err != 0)
    76     Fatal("posix_spawnattr_setsigmask: %s", strerror(err));
    77   // Signals which are set to be caught in the calling process image are set to
    78   // default action in the new process image, so no explicit
    79   // POSIX_SPAWN_SETSIGDEF parameter is needed.
    80 
    81   if (!use_console_) {
    82     // Put the child in its own process group, so ctrl-c won't reach it.
    83     flags |= POSIX_SPAWN_SETPGROUP;
    84     // No need to posix_spawnattr_setpgroup(&attr, 0), it's the default.
    85 
    86     // Open /dev/null over stdin.
    87     err = posix_spawn_file_actions_addopen(&action, 0, "/dev/null", O_RDONLY,
    88           0);
    89     if (err != 0) {
    90       Fatal("posix_spawn_file_actions_addopen: %s", strerror(err));
    91     }
     54  pid_ = fork();
     55  if (pid_ < 0)
     56    Fatal("fork: %s", strerror(errno));
     57
     58  if (pid_ == 0) {
     59    close(output_pipe[0]);
     60
     61    // Track which fd we use to report errors on.
     62    int error_pipe = output_pipe[1];
     63    do {
     64      if (sigaction(SIGINT, &set->old_int_act_, 0) < 0)
     65        break;
     66      if (sigaction(SIGTERM, &set->old_term_act_, 0) < 0)
     67        break;
     68      if (sigaction(SIGHUP, &set->old_hup_act_, 0) < 0)
     69        break;
     70      if (sigprocmask(SIG_SETMASK, &set->old_mask_, 0) < 0)
     71        break;
     72
     73      if (!use_console_) {
     74        // Put the child in its own process group, so ctrl-c won't reach it.
     75        if (setpgid(0, 0) < 0)
     76          break;
     77
     78        // Open /dev/null over stdin.
     79        int devnull = open("/dev/null", O_RDONLY);
     80        if (devnull < 0)
     81          break;
     82        if (dup2(devnull, 0) < 0)
     83          break;
     84        close(devnull);
     85
     86        if (dup2(output_pipe[1], 1) < 0 ||
     87            dup2(output_pipe[1], 2) < 0)
     88          break;
     89
     90        // Now can use stderr for errors.
     91        error_pipe = 2;
     92        close(output_pipe[1]);
     93      }
     94      // In the console case, output_pipe is still inherited by the child and
     95      // closed when the subprocess finishes, which then notifies ninja.
    9296
    93     err = posix_spawn_file_actions_adddup2(&action, output_pipe[1], 1);
    94     if (err != 0)
    95       Fatal("posix_spawn_file_actions_adddup2: %s", strerror(err));
    96     err = posix_spawn_file_actions_adddup2(&action, output_pipe[1], 2);
    97     if (err != 0)
    98       Fatal("posix_spawn_file_actions_adddup2: %s", strerror(err));
    99     err = posix_spawn_file_actions_addclose(&action, output_pipe[1]);
    100     if (err != 0)
    101       Fatal("posix_spawn_file_actions_addclose: %s", strerror(err));
    102     // In the console case, output_pipe is still inherited by the child and
    103     // closed when the subprocess finishes, which then notifies ninja.
    104   }
    105 #ifdef POSIX_SPAWN_USEVFORK
    106   flags |= POSIX_SPAWN_USEVFORK;
    107 #endif
    108 
    109   err = posix_spawnattr_setflags(&attr, flags);
    110   if (err != 0)
    111     Fatal("posix_spawnattr_setflags: %s", strerror(err));
    112 
    113   const char* spawned_args[] = { "/bin/sh", "-c", command.c_str(), NULL };
    114   err = posix_spawn(&pid_, "/bin/sh", &action, &attr,
    115         const_cast<char**>(spawned_args), environ);
    116   if (err != 0)
    117     Fatal("posix_spawn: %s", strerror(err));
    118 
    119   err = posix_spawnattr_destroy(&attr);
    120   if (err != 0)
    121     Fatal("posix_spawnattr_destroy: %s", strerror(err));
    122   err = posix_spawn_file_actions_destroy(&action);
    123   if (err != 0)
    124     Fatal("posix_spawn_file_actions_destroy: %s", strerror(err));
     97      execl("/bin/sh", "/bin/sh", "-c", command.c_str(), (char *) NULL);
     98    } while (false);
     99
     100    // If we get here, something went wrong; the execl should have
     101    // replaced us.
     102    char* err = strerror(errno);
     103    if (write(error_pipe, err, strlen(err)) < 0) {
     104      // If the write fails, there's nothing we can do.
     105      // But this block seems necessary to silence the warning.
     106     }
     107    _exit(1);
     108    }
    125109
    126110  close(output_pipe[1]);
    127111  return true;
  • src/subprocess_test.cc

    diff --git src/subprocess_test.cc src/subprocess_test.cc
    index 0a8c206..672a2f1 100644
    TEST_F(SubprocessTest, SetWithLots) { 
    224224  rlimit rlim;
    225225  ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlim));
    226226  if (rlim.rlim_cur < kNumProcs) {
    227     printf("Raise [ulimit -n] above %u (currently %lu) to make this test go\n",
    228            kNumProcs, rlim.rlim_cur);
     227    printf("Raise [ulimit -n] well above %u (currently %lu) to make this test go\n", kNumProcs, rlim.rlim_cur);
    229228    return;
    230229  }
    231230