blob: ed4d0dd42fe964fbd8cf2cf327215646167fb381 [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
Tyler Chatowd5db0422022-03-02 20:56:15 -080078 std::string_view full_path() const { return full_path_; }
79
James Kuszmauld42edb42022-01-07 18:00:16 -080080 const std::string &GetStdout();
81 const std::string &GetStderr();
82 std::optional<int> exit_code() const { return exit_code_; }
83
James Kuszmaul3224b8e2022-01-07 19:00:39 -080084 private:
James Kuszmauld42edb42022-01-07 18:00:16 -080085 typedef aos::util::ScopedPipe::PipePair PipePair;
86 void set_args(
87 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
88 &args);
89
James Kuszmaul3224b8e2022-01-07 19:00:39 -080090 void DoStart();
91
92 void DoStop(bool restart);
93
94 void QueueStart();
95
Tyler Chatowd5db0422022-03-02 20:56:15 -080096 // Queues start if autorestart set, otherwise moves state to stopped.
97 void MaybeQueueRestart();
98
James Kuszmaul3224b8e2022-01-07 19:00:39 -080099 // Copy flatbuffer vector of strings to vector of std::string.
100 static std::vector<std::string> FbsVectorToVector(
101 const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> &v);
102
103 static std::optional<uid_t> FindUid(const char *name);
104 static std::optional<gid_t> FindPrimaryGidForUser(const char *name);
105
James Kuszmauld42edb42022-01-07 18:00:16 -0800106 void FetchOutputs();
107
108 // Provides an std::vector of the args (such that CArgs().data() ends up being
109 // suitable to pass to execve()).
110 // The points are invalidated when args_ changes (e.g., due to a set_args
111 // call).
112 std::vector<char *> CArgs();
113
Tyler Chatowd5db0422022-03-02 20:56:15 -0800114 // Resolves the path to the binary from the PATH environment variable. On
115 // success, updates full_path_ to the absolute path to the binary and the
116 // checksum_ to the hex-encoded sha256 hash of the file; returns true. On
117 // failure, returns false.
118 bool UpdatePathAndChecksum();
119
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800120 // Next unique id for all applications
121 static inline uint64_t next_id_ = 0;
122
Tyler Chatowd5db0422022-03-02 20:56:15 -0800123 static constexpr size_t kSha256HexStrSize = 256 / CHAR_BIT * 2;
124
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800125 std::string name_;
126 std::string path_;
Tyler Chatowd5db0422022-03-02 20:56:15 -0800127 std::string full_path_;
128 std::array<char, kSha256HexStrSize> checksum_{"DEADBEEF"};
James Kuszmauld42edb42022-01-07 18:00:16 -0800129 std::vector<std::string> args_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800130 std::string user_name_;
131 std::optional<uid_t> user_;
132 std::optional<gid_t> group_;
133
James Kuszmauld42edb42022-01-07 18:00:16 -0800134 bool capture_stdout_ = false;
135 PipePair stdout_pipes_;
136 std::string stdout_;
137 bool capture_stderr_ = false;
138 PipePair stderr_pipes_;
139 std::string stderr_;
140
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800141 pid_t pid_ = -1;
James Kuszmauld42edb42022-01-07 18:00:16 -0800142 PipePair status_pipes_;
143 uint64_t id_ = 0;
144 std::optional<int> exit_code_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800145 aos::monotonic_clock::time_point start_time_, exit_time_;
146 bool queue_restart_ = false;
147 bool terminating_ = false;
James Kuszmauld42edb42022-01-07 18:00:16 -0800148 bool autostart_ = false;
149 bool autorestart_ = false;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800150
151 aos::starter::State status_ = aos::starter::State::STOPPED;
152 aos::starter::LastStopReason stop_reason_ =
153 aos::starter::LastStopReason::STOP_REQUESTED;
154
155 aos::EventLoop *event_loop_;
James Kuszmauld42edb42022-01-07 18:00:16 -0800156 aos::TimerHandler *start_timer_, *restart_timer_, *stop_timer_, *pipe_timer_,
157 *child_status_handler_;
James Kuszmaul3224b8e2022-01-07 19:00:39 -0800158
159 std::function<void()> on_change_;
160
161 DISALLOW_COPY_AND_ASSIGN(Application);
162};
163
164} // namespace aos::starter
James Kuszmauld42edb42022-01-07 18:00:16 -0800165#endif // AOS_STARTER_SUBPROCESS_H_