| // Copyright 2015 The Crashpad Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef CRASHPAD_TEST_WIN_WIN_CHILD_PROCESS_H_ |
| #define CRASHPAD_TEST_WIN_WIN_CHILD_PROCESS_H_ |
| |
| #include <memory> |
| |
| #include "util/file/file_io.h" |
| #include "util/win/scoped_handle.h" |
| |
| namespace crashpad { |
| namespace test { |
| |
| //! \brief Facilitates the launching of child processes from unit tests. |
| class WinChildProcess { |
| public: |
| //! \brief Groups handles used to communicate with, observe, and manage a |
| //! child process. |
| struct Handles { |
| //! \brief A handle to read from an anonymous pipe shared with the child |
| //! process. |
| ScopedFileHANDLE read; |
| //! \brief A handle to write to an anonymous pipe shared with the child |
| //! process. |
| ScopedFileHANDLE write; |
| //! \brief A handle to the child process. |
| ScopedKernelHANDLE process; |
| }; |
| |
| WinChildProcess(); |
| |
| WinChildProcess(const WinChildProcess&) = delete; |
| WinChildProcess& operator=(const WinChildProcess&) = delete; |
| |
| virtual ~WinChildProcess() {} |
| |
| //! \brief Returns true if the current process is a child process. |
| static bool IsChildProcess(); |
| |
| //! \brief Runs the child process defined by T if the current process is a |
| //! child process; does not return in that case. Otherwise, returns. |
| template <class T> |
| static void EntryPoint() { |
| if (IsChildProcess()) { |
| // The static_cast here will cause a compiler failure if T is not a |
| // subclass of WinChildProcess. It's the constructor of WinChildProcess |
| // that performs the pipe handshake with the parent process (without which |
| // we would have a hang). |
| T child_process; |
| int result = static_cast<WinChildProcess*>(&child_process)->Run(); |
| exit(result); |
| } |
| } |
| |
| //! \brief Launches a child process and returns the Handles for that process. |
| //! The process is guaranteed to be executing by the time this method |
| //! returns. Returns `nullptr` and logs a Google Test failure in case of |
| //! failure. |
| static std::unique_ptr<Handles> Launch(); |
| |
| protected: |
| //! \brief Returns a handle to read from an anonymous pipe shared with the |
| //! parent process. |
| //! |
| //! It is an error to call this after CloseReadPipe() has been called. |
| //! |
| //! \return The read pipe's file handle. |
| FileHandle ReadPipeHandle() const; |
| |
| //! \brief Returns a handle to write to an anonymous pipe shared with the |
| //! parent process. |
| //! |
| //! It is an error to call this after CloseWritePipe() has been called. |
| //! |
| //! \return The write pipe's file handle. |
| FileHandle WritePipeHandle() const; |
| |
| //! \brief Closes the read pipe. |
| //! |
| //! ReadPipeHandle() must not be called after this. |
| void CloseReadPipe(); |
| |
| //! \brief Closes the write pipe. |
| //! |
| //! An attempt to read from the read pipe in the parent process will indicate |
| //! end-of-file. WritePipeHandle() must not be called after this. |
| void CloseWritePipe(); |
| |
| private: |
| //! \brief The subclass-provided child routine. |
| //! |
| //! Subclasses must implement this method to define how the child operates. |
| //! Subclasses may exit with a failure status by using `LOG(FATAL)`, |
| //! `abort()`, or similar. They may also exit by returning their exit code |
| //! from this method. It is up to the client to observe and interpret the |
| //! child's exit code. |
| //! |
| //! \return The child process exit code. |
| virtual int Run() = 0; |
| |
| ScopedFileHANDLE pipe_read_; |
| ScopedFileHANDLE pipe_write_; |
| }; |
| |
| } // namespace test |
| } // namespace crashpad |
| |
| #endif // CRASHPAD_TEST_WIN_WIN_CHILD_PROCESS_H_ |