Ninja
subprocess.h
Go to the documentation of this file.
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_