File: child_process.h

package info (click to toggle)
anbox 0.0~git20190124-1
  • links: PTS, VCS
  • area: contrib
  • in suites: buster
  • size: 22,000 kB
  • sloc: cpp: 76,190; ansic: 7,434; sh: 1,350; xml: 818; java: 780; python: 390; makefile: 35; lisp: 7
file content (177 lines) | stat: -rw-r--r-- 5,475 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
 * 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 <http://www.gnu.org/licenses/>.
 *
 * Authored by: Thomas Voß <thomas.voss@canonical.com>
 */

#ifndef CORE_POSIX_CHILD_PROCESS_H_
#define CORE_POSIX_CHILD_PROCESS_H_

#include <core/posix/process.h>
#include <core/posix/standard_stream.h>
#include <core/posix/visibility.h>

#include <core/signal.h>

#include <iosfwd>
#include <functional>

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<DeathObserver> create_once_with_signal_trap(
                std::shared_ptr<SignalTrap> 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<ChildProcess>& 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<posix::exit::Status()>&, const StandardStream&);
    friend ChildProcess vfork(const std::function<posix::exit::Status()>&, 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<Private> d;
};
}
}

#endif // CORE_POSIX_CHILD_PROCESS_H_