/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef CORE_POSIX_CHILD_PROCESS_H_ #define CORE_POSIX_CHILD_PROCESS_H_ #include #include #include #include #include #include namespace core { namespace posix { /** * @brief The Process class models a child process of this process. * * In addition to the functionality offered by the Process class, an instance * of ChildProcess offers functionality to wait for status changes of the child * process and to access the child process's standard streams if they have been * redirected when forking or exec'ing. */ class CORE_POSIX_DLL_PUBLIC ChildProcess : public Process { public: /** * @brief The DeathObserver class observes child process' states and emits a signal when a monitored child has died. * * Please note that the name of this class is morbid for a reason: Listening * for SIGCHLD is not enough to catch all dying children. Whenever a SIGCHLD is * received, we have to wait for all the children of this process and reap all * monitored ones. We are thus changing state and potentially race with other * wait operations on children. * */ class DeathObserver { public: /** * @brief Creates the unique instance of class DeathObserver. * @throw std::logic_error if the given SignalTrap instance does not trap Signal::sig_chld. * @throw std::runtime_error if there already is an instance of the death observer. */ static std::unique_ptr create_once_with_signal_trap( std::shared_ptr trap); DeathObserver(const DeathObserver&) = delete; virtual ~DeathObserver() = default; DeathObserver& operator=(const DeathObserver&) = delete; bool operator==(const DeathObserver&) const = delete; /** * @brief add adds the specified child to the list of observed child processes. * @param child The child to be observed. * @return true iff the child has been added to the list of observed child processes. */ virtual bool add(const ChildProcess& child) = 0; /** * @brief has checks whether the specified child is observed. * @param child The child to check for. * @return true iff the specified child is observed for state changes. */ virtual bool has(const ChildProcess& child) const = 0; /** * @brief child_died is emitted whenever an observed child ceases to exist. */ virtual const core::Signal& child_died() const = 0; /** * @brief Checks and reaps all child processes registered with the observer instance. */ virtual void on_sig_child() = 0; protected: DeathObserver() = default; }; /** * @brief Creates an invalid ChildProcess. * @return An invalid ChildProcess instance. */ static ChildProcess invalid(); ~ChildProcess(); /** * @brief Wait for the child process to change state. * @param [in] flags Alters the behavior of the wait operation. * @return Result of the wait operation, as well as information about the * reasons for a child process's state change. */ wait::Result wait_for(const wait::Flags& flags); /** * @brief Mark the child process to not to be killed when the ChildProcess * instance goes away. */ void dont_kill_on_cleanup(); #ifndef ANDROID /** * @brief Access this process's stderr. */ std::istream& cerr(); /** * @brief Access this process's stdin. */ std::ostream& cin(); /** * @brief Access this process's stdout. */ std::istream& cout(); #endif private: friend ChildProcess fork(const std::function&, const StandardStream&); friend ChildProcess vfork(const std::function&, const StandardStream&); class CORE_POSIX_DLL_LOCAL Pipe { public: static Pipe invalid(); Pipe(); Pipe(const Pipe& rhs); ~Pipe(); Pipe& operator=(const Pipe& rhs); int read_fd() const; void close_read_fd(); int write_fd() const; void close_write_fd(); private: Pipe(int fds[2]); int fds[2]; }; CORE_POSIX_DLL_LOCAL ChildProcess(pid_t pid, const Pipe& stdin, const Pipe& stdout, const Pipe& stderr); struct CORE_POSIX_DLL_LOCAL Private; std::shared_ptr d; }; } } #endif // CORE_POSIX_CHILD_PROCESS_H_