blob: 9ee9e31b38bc151c66c9fac59b9740d680881ebe [file] [log] [blame]
James Kuszmaul3224b8e2022-01-07 19:00:39 -08001#ifndef AOS_STARTER_SUBPROCESS_H_
2#define AOS_STARTER_SUBPROCESS_H_
3
James Kuszmauld42edb42022-01-07 18:00:16 -08004#include <memory>
James Kuszmaul3224b8e2022-01-07 19:00:39 -08005#include <string>
James Kuszmauld42edb42022-01-07 18:00:16 -08006#include <tuple>
James Kuszmaul3224b8e2022-01-07 19:00:39 -08007#include <vector>
8
9#include "aos/events/event_loop.h"
10#include "aos/events/shm_event_loop.h"
11#include "aos/starter/starter_generated.h"
12#include "aos/starter/starter_rpc_generated.h"
13#include "aos/util/scoped_pipe.h"
14
15namespace aos::starter {
16
17// Registers a signalfd listener with the given event loop and calls callback
18// whenever a signal is received.
19class SignalListener {
20 public:
21 SignalListener(aos::ShmEventLoop *loop,
22 std::function<void(signalfd_siginfo)> callback);
23 SignalListener(aos::ShmEventLoop *loop,
24 std::function<void(signalfd_siginfo)> callback,
25 std::initializer_list<unsigned int> signals);
26
27 ~SignalListener();
28
29 private:
30 aos::ShmEventLoop *loop_;
31 std::function<void(signalfd_siginfo)> callback_;
32 aos::ipc_lib::SignalFd signalfd_;
33
34 DISALLOW_COPY_AND_ASSIGN(SignalListener);
35};
36
37// Manages a running process, allowing starting and stopping, and restarting
38// automatically.
39class Application {
40 public:
James Kuszmauld42edb42022-01-07 18:00:16 -080041 Application(const aos::Application *application, aos::EventLoop *event_loop,
42 std::function<void()> on_change);
43
44 Application(std::string_view name, std::string_view executable_name,
James Kuszmaul3224b8e2022-01-07 19:00:39 -080045 aos::EventLoop *event_loop, std::function<void()> on_change);
46
47 flatbuffers::Offset<aos::starter::ApplicationStatus> PopulateStatus(
48 flatbuffers::FlatBufferBuilder *builder);
James Kuszmauld42edb42022-01-07 18:00:16 -080049 aos::starter::State status() const { return status_; };
James Kuszmaul3224b8e2022-01-07 19:00:39 -080050
51 // Returns the last pid of this process. -1 if not started yet.
52 pid_t get_pid() const { return pid_; }
53
54 // Handles a SIGCHLD signal received by the parent. Does nothing if this
55 // process was not the target. Returns true if this Application should be
56 // removed.
57 bool MaybeHandleSignal();
James Kuszmauld42edb42022-01-07 18:00:16 -080058 void DisableChildDeathPolling() { child_status_handler_->Disable(); }
James Kuszmaul3224b8e2022-01-07 19:00:39 -080059
60 // Handles a command. May do nothing if application is already in the desired
61 // state.
62 void HandleCommand(aos::starter::Command cmd);
63
64 void Start() { HandleCommand(aos::starter::Command::START); }
65
66 void Stop() { HandleCommand(aos::starter::Command::STOP); }
67
68 void Terminate();
69
James Kuszmauld42edb42022-01-07 18:00:16 -080070 void set_args(std::vector<std::string> args);
71 void set_capture_stdout(bool capture);
72 void set_capture_stderr(bool capture);
James Kuszmaul3224b8e2022-01-07 19:00:39 -080073
74 bool autostart() const { return autostart_; }
75
76 bool autorestart() const { return autorestart_; }
77
James Kuszmauld42edb42022-01-07 18:00:16 -080078 const std::string &GetStdout();
79 const std::string &GetStderr();
80 std::optional<int> exit_code() const { return exit_code_; }
81
James Kuszmaul3224b8e2022-01-07 19:00:39 -080082 private:
James Kuszmauld42edb42022-01-07 18:00:16 -080083 typedef aos::util::ScopedPipe::PipePair PipePair;
84 void set_args(
85 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
86 &args);
87
James Kuszmaul3224b8e2022-01-07 19:00:39 -080088 void DoStart();
89
90 void DoStop(bool restart);
91
92 void QueueStart();
93
94 // Copy flatbuffer vector of strings to vector of std::string.
95 static std::vector<std::string> FbsVectorToVector(
96 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> &v);
97
98 static std::optional<uid_t> FindUid(const char *name);
99 static std::optional<gid_t> FindPrimaryGidForUser(const char *name);
100
James Kuszmauld42edb42022-01-07 18:00:16 -0800101 void FetchOutputs();
102
103 // Provides an std::vector of the args (such that CArgs().data() ends up being
104 // suitable to pass to execve()).
105 // The points are invalidated when args_ changes (e.g., due to a set_args
106 // call).
107 std::vector<char *> CArgs();
108
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800109 // Next unique id for all applications
110 static inline uint64_t next_id_ = 0;
111
112 std::string name_;
113 std::string path_;
James Kuszmauld42edb42022-01-07 18:00:16 -0800114 std::vector<std::string> args_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800115 std::string user_name_;
116 std::optional<uid_t> user_;
117 std::optional<gid_t> group_;
118
James Kuszmauld42edb42022-01-07 18:00:16 -0800119 bool capture_stdout_ = false;
120 PipePair stdout_pipes_;
121 std::string stdout_;
122 bool capture_stderr_ = false;
123 PipePair stderr_pipes_;
124 std::string stderr_;
125
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800126 pid_t pid_ = -1;
James Kuszmauld42edb42022-01-07 18:00:16 -0800127 PipePair status_pipes_;
128 uint64_t id_ = 0;
129 std::optional<int> exit_code_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800130 aos::monotonic_clock::time_point start_time_, exit_time_;
131 bool queue_restart_ = false;
132 bool terminating_ = false;
James Kuszmauld42edb42022-01-07 18:00:16 -0800133 bool autostart_ = false;
134 bool autorestart_ = false;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800135
136 aos::starter::State status_ = aos::starter::State::STOPPED;
137 aos::starter::LastStopReason stop_reason_ =
138 aos::starter::LastStopReason::STOP_REQUESTED;
139
140 aos::EventLoop *event_loop_;
James Kuszmauld42edb42022-01-07 18:00:16 -0800141 aos::TimerHandler *start_timer_, *restart_timer_, *stop_timer_, *pipe_timer_,
142 *child_status_handler_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800143
144 std::function<void()> on_change_;
145
146 DISALLOW_COPY_AND_ASSIGN(Application);
147};
148
149} // namespace aos::starter
James Kuszmauld42edb42022-01-07 18:00:16 -0800150#endif // AOS_STARTER_SUBPROCESS_H_