Ninja
subprocess.h
Go to the documentation of this file.
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 using namespace std;
22 
23 #ifdef _WIN32
24 #include <windows.h>
25 #else
26 #include <signal.h>
27 #endif
28 
29 // ppoll() exists on FreeBSD, but only on newer versions.
30 #ifdef __FreeBSD__
31 # include <sys/param.h>
32 # if defined USE_PPOLL && __FreeBSD_version < 1002000
33 # undef USE_PPOLL
34 # endif
35 #endif
36 
37 #include "exit_status.h"
38 
39 /// Subprocess wraps a single async subprocess. It is entirely
40 /// passive: it expects the caller to notify it when its fds are ready
41 /// for reading, as well as call Finish() to reap the child once done()
42 /// is true.
43 struct Subprocess {
44  ~Subprocess();
45 
46  /// Returns ExitSuccess on successful process exit, ExitInterrupted if
47  /// the process was interrupted, ExitFailure if it otherwise failed.
48  ExitStatus Finish();
49 
50  bool Done() const;
51 
52  const string& GetOutput() const;
53 
54  private:
55  Subprocess(bool use_console);
56  bool Start(struct SubprocessSet* set, const string& command);
57  void OnPipeReady();
58 
59  string buf_;
60 
61 #ifdef _WIN32
62  /// Set up pipe_ as the parent-side pipe of the subprocess; return the
63  /// other end of the pipe, usable in the child process.
64  HANDLE SetupPipe(HANDLE ioport);
65 
66  HANDLE child_;
67  HANDLE pipe_;
68  OVERLAPPED overlapped_;
69  char overlapped_buf_[4 << 10];
70  bool is_reading_;
71 #else
72  int fd_;
73  pid_t pid_;
74 #endif
76 
77  friend struct SubprocessSet;
78 };
79 
80 /// SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
81 /// DoWork() waits for any state change in subprocesses; finished_
82 /// is a queue of subprocesses as they finish.
83 struct SubprocessSet {
84  SubprocessSet();
85  ~SubprocessSet();
86 
87  Subprocess* Add(const string& command, bool use_console = false);
88  bool DoWork();
89  Subprocess* NextFinished();
90  void Clear();
91 
92  vector<Subprocess*> running_;
93  queue<Subprocess*> finished_;
94 
95 #ifdef _WIN32
96  static BOOL WINAPI NotifyInterrupted(DWORD dwCtrlType);
97  static HANDLE ioport_;
98 #else
99  static void SetInterruptedFlag(int signum);
100  static void HandlePendingInterruption();
101  /// Store the signal number that causes the interruption.
102  /// 0 if not interruption.
103  static int interrupted_;
104 
105  static bool IsInterrupted() { return interrupted_ != 0; }
106 
107  struct sigaction old_int_act_;
108  struct sigaction old_term_act_;
109  struct sigaction old_hup_act_;
110  sigset_t old_mask_;
111 #endif
112 };
113 
114 #endif // NINJA_SUBPROCESS_H_
SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
Definition: subprocess.h:83
bool use_console_
Definition: subprocess.h:75
vector< Subprocess * > running_
Definition: subprocess.h:92
string buf_
Definition: subprocess.h:59
Subprocess wraps a single async subprocess.
Definition: subprocess.h:43
static bool IsInterrupted()
Definition: subprocess.h:105
static int interrupted_
Store the signal number that causes the interruption.
Definition: subprocess.h:103
ExitStatus
Definition: exit_status.h:18
sigset_t old_mask_
Definition: subprocess.h:110
pid_t pid_
Definition: subprocess.h:73
queue< Subprocess * > finished_
Definition: subprocess.h:93