blob: a4d7cbb52e506ebe261498edc230a1c6f9ccc4c2 [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"
James Kuszmaul6295a642022-03-22 15:23:59 -070014#include "aos/util/top.h"
James Kuszmaul3224b8e2022-01-07 19:00:39 -080015
16namespace aos::starter {
17
18// Registers a signalfd listener with the given event loop and calls callback
19// whenever a signal is received.
20class SignalListener {
21 public:
22 SignalListener(aos::ShmEventLoop *loop,
23 std::function<void(signalfd_siginfo)> callback);
24 SignalListener(aos::ShmEventLoop *loop,
25 std::function<void(signalfd_siginfo)> callback,
26 std::initializer_list<unsigned int> signals);
27
28 ~SignalListener();
29
30 private:
31 aos::ShmEventLoop *loop_;
32 std::function<void(signalfd_siginfo)> callback_;
33 aos::ipc_lib::SignalFd signalfd_;
34
35 DISALLOW_COPY_AND_ASSIGN(SignalListener);
36};
37
38// Manages a running process, allowing starting and stopping, and restarting
39// automatically.
40class Application {
41 public:
James Kuszmauld42edb42022-01-07 18:00:16 -080042 Application(const aos::Application *application, aos::EventLoop *event_loop,
43 std::function<void()> on_change);
44
45 Application(std::string_view name, std::string_view executable_name,
James Kuszmaul3224b8e2022-01-07 19:00:39 -080046 aos::EventLoop *event_loop, std::function<void()> on_change);
47
48 flatbuffers::Offset<aos::starter::ApplicationStatus> PopulateStatus(
James Kuszmaul6295a642022-03-22 15:23:59 -070049 flatbuffers::FlatBufferBuilder *builder, util::Top *top);
James Kuszmauld42edb42022-01-07 18:00:16 -080050 aos::starter::State status() const { return status_; };
James Kuszmaul3224b8e2022-01-07 19:00:39 -080051
52 // Returns the last pid of this process. -1 if not started yet.
53 pid_t get_pid() const { return pid_; }
54
55 // Handles a SIGCHLD signal received by the parent. Does nothing if this
56 // process was not the target. Returns true if this Application should be
57 // removed.
58 bool MaybeHandleSignal();
James Kuszmauld42edb42022-01-07 18:00:16 -080059 void DisableChildDeathPolling() { child_status_handler_->Disable(); }
James Kuszmaul3224b8e2022-01-07 19:00:39 -080060
61 // Handles a command. May do nothing if application is already in the desired
62 // state.
63 void HandleCommand(aos::starter::Command cmd);
64
65 void Start() { HandleCommand(aos::starter::Command::START); }
66
67 void Stop() { HandleCommand(aos::starter::Command::STOP); }
68
69 void Terminate();
70
James Kuszmauld42edb42022-01-07 18:00:16 -080071 void set_args(std::vector<std::string> args);
72 void set_capture_stdout(bool capture);
73 void set_capture_stderr(bool capture);
James Kuszmaul3224b8e2022-01-07 19:00:39 -080074
75 bool autostart() const { return autostart_; }
76
77 bool autorestart() const { return autorestart_; }
78
James Kuszmauld42edb42022-01-07 18:00:16 -080079 const std::string &GetStdout();
80 const std::string &GetStderr();
81 std::optional<int> exit_code() const { return exit_code_; }
82
James Kuszmaul3224b8e2022-01-07 19:00:39 -080083 private:
James Kuszmauld42edb42022-01-07 18:00:16 -080084 typedef aos::util::ScopedPipe::PipePair PipePair;
85 void set_args(
86 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
87 &args);
88
James Kuszmaul3224b8e2022-01-07 19:00:39 -080089 void DoStart();
90
91 void DoStop(bool restart);
92
93 void QueueStart();
94
95 // Copy flatbuffer vector of strings to vector of std::string.
96 static std::vector<std::string> FbsVectorToVector(
97 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> &v);
98
99 static std::optional<uid_t> FindUid(const char *name);
100 static std::optional<gid_t> FindPrimaryGidForUser(const char *name);
101
James Kuszmauld42edb42022-01-07 18:00:16 -0800102 void FetchOutputs();
103
104 // Provides an std::vector of the args (such that CArgs().data() ends up being
105 // suitable to pass to execve()).
106 // The points are invalidated when args_ changes (e.g., due to a set_args
107 // call).
108 std::vector<char *> CArgs();
109
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800110 // Next unique id for all applications
111 static inline uint64_t next_id_ = 0;
112
113 std::string name_;
114 std::string path_;
James Kuszmauld42edb42022-01-07 18:00:16 -0800115 std::vector<std::string> args_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800116 std::string user_name_;
117 std::optional<uid_t> user_;
118 std::optional<gid_t> group_;
119
James Kuszmauld42edb42022-01-07 18:00:16 -0800120 bool capture_stdout_ = false;
121 PipePair stdout_pipes_;
122 std::string stdout_;
123 bool capture_stderr_ = false;
124 PipePair stderr_pipes_;
125 std::string stderr_;
126
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800127 pid_t pid_ = -1;
James Kuszmauld42edb42022-01-07 18:00:16 -0800128 PipePair status_pipes_;
129 uint64_t id_ = 0;
130 std::optional<int> exit_code_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800131 aos::monotonic_clock::time_point start_time_, exit_time_;
132 bool queue_restart_ = false;
133 bool terminating_ = false;
James Kuszmauld42edb42022-01-07 18:00:16 -0800134 bool autostart_ = false;
135 bool autorestart_ = false;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800136
137 aos::starter::State status_ = aos::starter::State::STOPPED;
138 aos::starter::LastStopReason stop_reason_ =
139 aos::starter::LastStopReason::STOP_REQUESTED;
140
141 aos::EventLoop *event_loop_;
James Kuszmauld42edb42022-01-07 18:00:16 -0800142 aos::TimerHandler *start_timer_, *restart_timer_, *stop_timer_, *pipe_timer_,
143 *child_status_handler_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800144
145 std::function<void()> on_change_;
146
147 DISALLOW_COPY_AND_ASSIGN(Application);
148};
149
150} // namespace aos::starter
James Kuszmauld42edb42022-01-07 18:00:16 -0800151#endif // AOS_STARTER_SUBPROCESS_H_