Ninja
|
00001 // Copyright 2012 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #ifndef NINJA_SUBPROCESS_H_ 00016 #define NINJA_SUBPROCESS_H_ 00017 00018 #include <string> 00019 #include <vector> 00020 #include <queue> 00021 using namespace std; 00022 00023 #ifdef _WIN32 00024 #include <windows.h> 00025 #else 00026 #include <signal.h> 00027 #endif 00028 00029 #include "exit_status.h" 00030 00031 /// Subprocess wraps a single async subprocess. It is entirely 00032 /// passive: it expects the caller to notify it when its fds are ready 00033 /// for reading, as well as call Finish() to reap the child once done() 00034 /// is true. 00035 struct Subprocess { 00036 ~Subprocess(); 00037 00038 /// Returns ExitSuccess on successful process exit, ExitInterrupted if 00039 /// the process was interrupted, ExitFailure if it otherwise failed. 00040 ExitStatus Finish(); 00041 00042 bool Done() const; 00043 00044 const string& GetOutput() const; 00045 00046 private: 00047 Subprocess(); 00048 bool Start(struct SubprocessSet* set, const string& command); 00049 void OnPipeReady(); 00050 00051 string buf_; 00052 00053 #ifdef _WIN32 00054 /// Set up pipe_ as the parent-side pipe of the subprocess; return the 00055 /// other end of the pipe, usable in the child process. 00056 HANDLE SetupPipe(HANDLE ioport); 00057 00058 HANDLE child_; 00059 HANDLE pipe_; 00060 OVERLAPPED overlapped_; 00061 char overlapped_buf_[4 << 10]; 00062 bool is_reading_; 00063 #else 00064 int fd_; 00065 pid_t pid_; 00066 #endif 00067 00068 friend struct SubprocessSet; 00069 }; 00070 00071 /// SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses. 00072 /// DoWork() waits for any state change in subprocesses; finished_ 00073 /// is a queue of subprocesses as they finish. 00074 struct SubprocessSet { 00075 SubprocessSet(); 00076 ~SubprocessSet(); 00077 00078 Subprocess* Add(const string& command); 00079 bool DoWork(); 00080 Subprocess* NextFinished(); 00081 void Clear(); 00082 00083 vector<Subprocess*> running_; 00084 queue<Subprocess*> finished_; 00085 00086 #ifdef _WIN32 00087 static BOOL WINAPI NotifyInterrupted(DWORD dwCtrlType); 00088 static HANDLE ioport_; 00089 #else 00090 static void SetInterruptedFlag(int signum); 00091 static bool interrupted_; 00092 00093 struct sigaction old_act_; 00094 sigset_t old_mask_; 00095 #endif 00096 }; 00097 00098 #endif // NINJA_SUBPROCESS_H_