github.com/maruel/nin@v0.0.0-20220112143044-f35891e3ce7e/src/subprocess.h (about)

     1  // Copyright 2012 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #ifndef NINJA_SUBPROCESS_H_
    16  #define NINJA_SUBPROCESS_H_
    17  
    18  #include <string>
    19  #include <vector>
    20  #include <queue>
    21  
    22  #ifdef _WIN32
    23  #include <windows.h>
    24  #else
    25  #include <signal.h>
    26  #endif
    27  
    28  // ppoll() exists on FreeBSD, but only on newer versions.
    29  #ifdef __FreeBSD__
    30  #  include <sys/param.h>
    31  #  if defined USE_PPOLL && __FreeBSD_version < 1002000
    32  #    undef USE_PPOLL
    33  #  endif
    34  #endif
    35  
    36  #include "exit_status.h"
    37  
    38  /// Subprocess wraps a single async subprocess.  It is entirely
    39  /// passive: it expects the caller to notify it when its fds are ready
    40  /// for reading, as well as call Finish() to reap the child once done()
    41  /// is true.
    42  struct Subprocess {
    43    ~Subprocess();
    44  
    45    /// Returns ExitSuccess on successful process exit, ExitInterrupted if
    46    /// the process was interrupted, ExitFailure if it otherwise failed.
    47    ExitStatus Finish();
    48  
    49    bool Done() const;
    50  
    51    const std::string& GetOutput() const;
    52  
    53   private:
    54    Subprocess(bool use_console);
    55    bool Start(struct SubprocessSet* set, const std::string& command);
    56    void OnPipeReady();
    57  
    58    std::string buf_;
    59  
    60  #ifdef _WIN32
    61    /// Set up pipe_ as the parent-side pipe of the subprocess; return the
    62    /// other end of the pipe, usable in the child process.
    63    HANDLE SetupPipe(HANDLE ioport);
    64  
    65    HANDLE child_;
    66    HANDLE pipe_;
    67    OVERLAPPED overlapped_;
    68    char overlapped_buf_[4 << 10];
    69    bool is_reading_;
    70  #else
    71    int fd_;
    72    pid_t pid_;
    73  #endif
    74    bool use_console_;
    75  
    76    friend struct SubprocessSet;
    77  };
    78  
    79  /// SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
    80  /// DoWork() waits for any state change in subprocesses; finished_
    81  /// is a queue of subprocesses as they finish.
    82  struct SubprocessSet {
    83    SubprocessSet();
    84    ~SubprocessSet();
    85  
    86    Subprocess* Add(const std::string& command, bool use_console = false);
    87    bool DoWork();
    88    Subprocess* NextFinished();
    89    void Clear();
    90  
    91    std::vector<Subprocess*> running_;
    92    std::queue<Subprocess*> finished_;
    93  
    94  #ifdef _WIN32
    95    static BOOL WINAPI NotifyInterrupted(DWORD dwCtrlType);
    96    static HANDLE ioport_;
    97  #else
    98    static void SetInterruptedFlag(int signum);
    99    static void HandlePendingInterruption();
   100    /// Store the signal number that causes the interruption.
   101    /// 0 if not interruption.
   102    static int interrupted_;
   103  
   104    static bool IsInterrupted() { return interrupted_ != 0; }
   105  
   106    struct sigaction old_int_act_;
   107    struct sigaction old_term_act_;
   108    struct sigaction old_hup_act_;
   109    sigset_t old_mask_;
   110  #endif
   111  };
   112  
   113  #endif // NINJA_SUBPROCESS_H_