- // \file child.hpp
- //
- // Copyright (C) 2014 MicroNeil Research Corporation.
- //
- // This program is part of the MicroNeil Research Open Library Project. For
- // more information go to http://www.microneil.com/OpenLibrary/index.html
- //
- // This program is free software; you can redistribute it and/or modify it
- // under the terms of the GNU General Public License as published by the
- // Free Software Foundation; either version 2 of the License, or (at your
- // option) any later version.
- //
- // This program is distributed in the hope that it will be useful, but WITHOUT
- // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- // more details.
- //
- // You should have received a copy of the GNU General Public License along with
- // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- // Place, Suite 330, Boston, MA 02111-1307 USA
- //==============================================================================
-
- /*
- \brief The child module provides classes to spawn and communicate
- with child processes.
- */
-
- #ifndef CHILD_HPP
- #define CHILD_HPP
-
- #ifdef _WIN32
- #include <windows.h>
- #endif
-
- #include <cstdint>
- #include <streambuf>
- #include <istream>
- #include <ostream>
- #include <string>
- #include <vector>
-
- namespace CodeDweller {
-
- /**
- \namespace CodeDweller
-
- The CodeDweller namespace contains components providing high-level
- functionality for applications.
-
- */
-
- /** Class that abstracts the creation of child processes.
-
- This class provides functionality to create a child process,
- communicate with the child process via streams and signals, and
- obtain the exit code of the child process.
-
- */
-
- class Child {
-
- private:
-
- /// Streambuf class for reading the standard output of the child
- /// process.
- class ReadStreambuf : public std::streambuf {
-
- friend class Child;
-
- public:
-
- /// Reader streambuf constructor.
- //
- // \param[in] bufferSize is the size in bytes of the input
- // buffer.
- //
- explicit ReadStreambuf(std::size_t bufferSize = 4096);
-
- #ifdef _WIN32
- /// Set the handle to read the standard output of the child
- /// process.
- //
- // \param[in] inHandle is the input handle for the standard
- // output of the child process.
- //
- void setInputHandle(HANDLE inHandle);
- #else
- /// Set the file descriptor to read the standard output of the
- /// child process.
- //
- // \param[in] inFd is the input file descriptor for the standard
- // output of the child process.
- //
- void setInputFileDescriptor(int inFd);
- #endif
-
- private:
-
- /** Return the number of bytes that can be read without
- blocking.
-
- This method checks if any input is available from the pipe,
- and returns the number of bytes in the input buffer plus 1.
- Reading that number of bytes will not block. Reading a
- larger number of bytes might block.
-
- \returns minimum number of bytes that can be read without
- blocking.
-
- */
- size_t numBytesAvailable() const;
-
- /// Override streambuf::underflow().
- int_type underflow();
-
- /// Copy constructor not implemented.
- ReadStreambuf(const ReadStreambuf &);
-
- /// Copy constructor not implemented.
- ReadStreambuf &operator=(const ReadStreambuf &);
-
- /// Input handle.
- #ifdef _WIN32
- HANDLE inputHandle;
- #else
- int inputFileDescriptor;
- #endif
-
- /// Read buffer.
- std::vector<char> buffer;
-
- };
-
- /// Streambuf class for writing to the standard input of the child
- /// process.
- //
- // Note: If an error occurs when writing the output from the
- // parent process, the output buffer is cleared.
- //
- class WriteStreambuf : public std::streambuf {
-
- public:
-
- /// Writer streambuf constructor.
- //
- // \param[in] bufferSize is the size in bytes of the input
- // buffer.
- //
- explicit WriteStreambuf(std::size_t bufferSize = 4096);
-
- #ifdef _WIN32
- /// Set the handle to write the standard input of the child
- /// process.
- //
- // \param[in] outHandle is the output handle for the standard
- // input of the child process.
- //
- void setOutputHandle(HANDLE outHandle);
- #else
- /// Set the file descriptor to write the standard input of the
- /// child process.
- //
- // \param[in] outFd is the output file descriptor for the
- // standard input of the child process.
- //
- void setOutputFileDescriptor(int outFd);
- #endif
-
- private:
-
- /// Flush the output buffer.
- void flushBuffer();
-
- /// Override streambuf::overflow().
- int_type overflow(int_type ch);
-
- /// Override streambuf::sync().
- int sync();
-
- /// Copy constructor not implemented.
- WriteStreambuf(const WriteStreambuf &);
-
- /// Copy constructor not implemented.
- WriteStreambuf &operator=(const WriteStreambuf &);
-
- /// Output handle.
- #ifdef _WIN32
- HANDLE outputHandle;
- #else
- int outputFileDescriptor;
- #endif
-
- /// Write buffer.
- std::vector<char> buffer;
-
- };
-
- /// Stream buffer for reading from the stdout of the child process;
- ReadStreambuf readStreambuf;
-
- /// Stream buffer for writing to the stdin of the child process;
- WriteStreambuf writeStreambuf;
-
- public:
-
- /** Constructor for spawning with command-line parameters.
-
- The constructor configures the object, but doesn't spawn the
- child process.
-
- \param[in] args contains the child executable file name and
- command-line parameters. args[0] contains the full path of the
- executable, and args[1] thru args[n] are the command-line
- parameters.
-
- \param[in] bufSize is the buffer size of the reader and writer
- streams used to communicate with the child process.
-
- */
- Child(std::vector<std::string> args, size_t bufSize = 4096);
-
- /** Constructor for spawning without command-line parameters.
-
- The constructor configures the object, but doesn't spawn the
- child process.
-
- \param[in] childpath contains the child executable file name.
-
- \param[in] bufSize is the buffer size of the reader and writer
- streams used to communicate with the child process.
-
- */
- Child(std::string childpath, size_t bufSize = 4096);
-
- /** Destructor terminates the child process. */
- ~Child();
-
- /// Input stream to read data from the child's standard output.
- std::istream reader;
-
- /** Get the number of bytes available for input.
-
- @returns number of bytes that can be read from reader without
- blocking.
-
- */
- size_t numBytesAvailable() const;
-
- /// Output stream to write data to the child's standard input.
- std::ostream writer;
-
- /** Spawn the child process.
-
- \throws runtime_error if an error occurs.
-
- */
- void run();
-
- /** Terminite the child process.
-
- \throws runtime_error if an error occurs.
-
- \throws logic_error if the child process is not running.
-
- */
- void terminate();
-
- /** Check whether the child process has exited.
-
- \returns True if the child process has exited, false
- otherwise.
-
- \throws runtime_error if an error occurs.
-
- \throws logic_error if the child process is not running.
-
- */
- bool isDone();
-
- /** Get the exit value of the child process.
-
- \returns The exit value of the child process if the child
- process has exited.
-
- \throws runtime_error if an error occurs.
-
- \throws logic_error if the child process has not exited.
-
- \throws logic_error if the child process is not running.
-
- */
- int32_t result();
-
- private:
-
- /// Exit code to use when terminating the child process.
- static const uint32_t terminateExitCode = 0;
-
- /// True if the child process was successfully started.
- bool childStarted;
-
- /// True if the child process has exited.
- bool childExited;
-
- /// Initialize data members.
- void init();
-
- /// Child executable path and command-line parameters.
- std::vector<std::string> cmdArgs;
-
- /// Child executable path and command-line parameters.
- std::string cmdline;
-
- #ifdef _WIN32
- /// Child's process handle.
- HANDLE childProcess;
-
- /// Child's thread handle.
- HANDLE childThread;
- #else
- /// Child process ID.
- pid_t childPid;
- #endif
-
- /// Exit value of the process.
- int32_t exitCode;
-
- /// True if the exit code has been obtained.
- bool exitCodeObtainedFlag;
-
- /// Return text for the most recent error.
- //
- // \returns Human-readable description of the most recent error.
- //
- static std::string getErrorText();
-
- };
-
- }
-
- #endif // CHILD_HPP
|