• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
75   bool use_console_;
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 
IsInterruptedSubprocessSet105   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_
115