blob: 979171172a1f68fa72ef700547c812486af13be9 [file] [log] [blame]
Honglin Yu7b6c1192020-09-16 10:07:17 +10001// Copyright 2021 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef ML_PROCESS_H_
6#define ML_PROCESS_H_
7
8#include <memory>
9#include <string>
10#include <unordered_map>
11
12#include <unistd.h>
13
Honglin Yuf3c47b32021-05-06 18:38:37 +100014#include <base/callback_forward.h>
Honglin Yu7b6c1192020-09-16 10:07:17 +100015#include <base/macros.h>
16#include <base/no_destructor.h>
17#include <base/process/process_metrics.h>
18#include <mojo/public/cpp/bindings/remote.h>
19#include <base/sequence_checker.h>
20
21#include "ml/machine_learning_service_impl.h"
22
23namespace ml {
24
25// A singleton class to store the global process information and provide
26// process management functions.
27// Usage: access the global instance by calling `Process::GetInstance()`.
28class Process {
29 public:
30 // The type of a process.
Honglin Yuf3c47b32021-05-06 18:38:37 +100031 // "kControlForTest" denotes the control process in unit tests (i.e. the
32 // process that runs the ml_service_test binary). "kSingleProcessForTest"
33 // means the program will not spawn worker processes and use one single
34 // process for testing.
Honglin Yu7b6c1192020-09-16 10:07:17 +100035 enum class Type {
36 kUnset = 0,
37 kControl = 1,
38 kWorker = 2,
Honglin Yuf3c47b32021-05-06 18:38:37 +100039 kControlForTest = 3, // Like control process but with less strict
40 // sandboxing for using in testing.
41 kSingleProcessForTest = 4, // Temporary, used by old single-process tests.
Honglin Yu7b6c1192020-09-16 10:07:17 +100042 };
43
44 // The exit code of a process.
45 enum ExitCode : int {
46 kSuccess = 0,
47 // Only for worker process used when its mojo connection with the control
48 // process breaks.
49 kWorkerDisconnectWithControl = 1,
50 kInvalidProcessType = 2,
51 kUnexpectedCommandLine = 3,
52 };
53
54 // The worker process info, containing object to contact and measure worker
55 // process in the control process.
56 struct WorkerInfo {
57 // The Mojo remote to call the worker process's `MachineLearningService`
58 // bindings.
59 mojo::Remote<chromeos::machine_learning::mojom::MachineLearningService>
60 remote;
61 // The process metrics object of the worker process.
62 std::unique_ptr<base::ProcessMetrics> process_metrics;
63 };
64
65 static Process* GetInstance();
66
67 int Run(int argc, char* argv[]);
68
69 // Gets the process type of current process.
70 Type GetType();
71
72 // Returns true if the worker process has been started successfully and the
73 // worker's pid is stored in `worker_pid`. Otherwise returns false and
74 // `worker_pid` is unchanged.
75 // The argument `model_name` has two usages:
76 // - it used in logging (like `metrics_model_name`).
77 // - it also determines which seccomp policy list to use in sandboxing the
78 // worker process.
79 bool SpawnWorkerProcessAndGetPid(const mojo::PlatformChannel& channel,
80 const std::string& model_name,
81 pid_t* worker_pid);
82
83 // Returns a reference of the remote of the worker process. The remote is hold
84 // in the `worker_pid_info_map_` object.
85 mojo::Remote<chromeos::machine_learning::mojom::MachineLearningService>&
86 SendMojoInvitationAndGetRemote(pid_t worker_pid,
87 mojo::PlatformChannel channel,
88 const std::string& model_name);
89
90 // Removes a worker process from metadata. This does not terminate the
91 // worker process.
92 void UnregisterWorkerProcess(pid_t pid);
93
94 const std::unordered_map<pid_t, WorkerInfo>& GetWorkerPidInfoMap();
95
Honglin Yuf3c47b32021-05-06 18:38:37 +100096 // Sets the process type. Only used in testing.
97 void SetTypeForTesting(Type type);
98
99 // Sets the path of mlservice. Only used in testing.
100 void SetMlServicePathForTesting(const std::string& path);
101
102 // Sets the `before_exit_worker_disconnect_handler_hook`, only used in
103 // testing.
104 void SetBeforeExitWorkerDisconnectHandlerHookForTesting(
105 base::RepeatingClosure hook);
106
107 // Returns if the current process is a control process (i.e. `kControl ||
108 // kControlForTest`).
109 bool IsControlProcess();
110
111 // Returns if the current process is a worker process (i.e. that will do the
112 // actually inference work, `kWorker || kSingleProcessForTest`).
113 bool IsWorkerProcess();
114
Honglin Yu7b6c1192020-09-16 10:07:17 +1000115 private:
116 friend base::NoDestructor<Process>;
117
118 Process();
119 ~Process();
120
121 // Can only be called by the control process.
122 void ControlProcessRun();
123
124 // Can only be called by the worker process.
125 // Input: the file descriptor used to bootstrap Mojo connection.
126 void WorkerProcessRun();
127
Honglin Yuf3c47b32021-05-06 18:38:37 +1000128 // The disconnect handler of control process for the mojo connection to the
129 // worker process.
130 void InternalPrimordialMojoPipeDisconnectHandler(pid_t child_pid);
131
Honglin Yu7b6c1192020-09-16 10:07:17 +1000132 // The type of current process.
133 Type process_type_;
134
135 // The file descriptor to bootstrap the mojo connection of current process.
136 // Only meaningful for worker process.
137 int mojo_bootstrap_fd_;
138
Honglin Yuf3c47b32021-05-06 18:38:37 +1000139 // Path to the ml_service binary. Normally (and by default) it is
140 // "/usr/bin/ml_service". We may change the value here for testing.
141 std::string ml_service_path_;
142
Honglin Yu7b6c1192020-09-16 10:07:17 +1000143 // The map from pid to the info of worker processes. Only meaningful for
144 // control process.
145 std::unordered_map<pid_t, WorkerInfo> worker_pid_info_map_;
146
Honglin Yuf3c47b32021-05-06 18:38:37 +1000147 // The function called in the `kControlForTesting` process at the last of
148 // disconnection handler of the mojo connection to the worker process, only
149 // used in testing.
150 base::RepeatingClosure before_exit_worker_disconnect_handler_hook_;
151
Honglin Yu7b6c1192020-09-16 10:07:17 +1000152 // Mainly used for guarding `worker_pid_info_map_`.
153 SEQUENCE_CHECKER(sequence_checker_);
154};
155
156} // namespace ml
157
158#endif // ML_PROCESS_H_