xref: /DragonReach/src/executor/service_executor/mod.rs (revision b40b6b4d2f72c30a382f9f18740fa73d7fc90721)
1 #[cfg(target_os = "dragonos")]
2 use drstd as std;
3 
4 use crate::{
5     error::runtime_error::{RuntimeError, RuntimeErrorType},
6     manager::{timer_manager::TimerManager, UnitManager},
7     parse::Segment,
8     unit::{
9         service::{ServiceType, ServiceUnit},
10         Unit, UnitState,
11     },
12 };
13 
14 use std::process::Command;
15 use std::process::Stdio;
16 use std::time::Duration;
17 use std::vec::Vec;
18 use std::{eprint, eprintln, print, println};
19 
20 use super::{Executor, ExitStatus};
21 
22 pub struct ServiceExecutor;
23 
24 impl ServiceExecutor {
25     /// ## Service执行器
26     pub fn exec(service: &mut ServiceUnit) -> Result<(), RuntimeError> {
27         // 通过服务启动类型分发
28         match *service.service_part().service_type() {
29             ServiceType::Simple => return Self::exec_simple(service),
30             ServiceType::Forking => return Self::exec_forking(service),
31             ServiceType::Dbus => return Self::exec_dbus(service),
32             ServiceType::Notify => return Self::exec_notify(service),
33             ServiceType::Idle => return Self::exec_idle(service),
34             ServiceType::OneShot => return Self::exec_one_shot(service),
35         };
36     }
37 
38     pub fn exec_simple(service: &mut ServiceUnit) -> Result<(), RuntimeError> {
39         //处理conflict
40         let conflicts = service.unit_base().unit_part().conflicts();
41         for u in conflicts {
42             // 如果有冲突项enable的时候,该unit不能启动
43             let mutex = UnitManager::get_unit_with_id(u).unwrap();
44             let unit = mutex.lock().unwrap();
45             if *unit.unit_base().state() == UnitState::Enabled {
46                 eprintln!(
47                     "{}: Service startup failed: conflict unit",
48                     unit.unit_base().unit_part().description()
49                 );
50                 return Err(RuntimeError::new(RuntimeErrorType::ExecFailed));
51             }
52         }
53 
54         //获取启动命令
55         let exec_start = service.service_part().exec_start();
56 
57         //TODO:设置uid与gid
58 
59         //处理ExecStartsPre,准备在服务启动前执行的命令
60         Self::exec_start_pre(service)?;
61 
62         //创建服务进程
63         //服务配置环境变量,配置工作目录
64         let proc = Command::new(&exec_start.path)
65             .args(&exec_start.cmd)
66             .current_dir(service.service_part().working_directory())
67             .envs(Vec::from(service.service_part().environment()))
68             .stderr(Stdio::inherit())
69             .stdout(Stdio::inherit())
70             .stdin(Stdio::inherit())
71             .spawn();
72 
73         match proc {
74             Ok(p) => {
75                 println!("Service running...");
76                 //修改service状态
77                 service.mut_unit_base().set_state(UnitState::Enabled);
78                 //启动成功后将Child加入全局管理的进程表
79                 UnitManager::push_running(service.unit_id(), p);
80                 //执行启动后命令
81                 Self::exec_start_pos(service)?;
82             }
83             Err(err) => {
84                 eprintln!("{}: Service startup failed: {}", exec_start.path, err);
85                 return Err(RuntimeError::new(RuntimeErrorType::ExecFailed));
86             }
87         }
88         Ok(())
89     }
90 
91     fn exec_dbus(_service: &ServiceUnit) -> Result<(), RuntimeError> {
92         Ok(())
93     }
94 
95     fn exec_forking(_service: &ServiceUnit) -> Result<(), RuntimeError> {
96         Ok(())
97     }
98 
99     // 此方法会改变service的启动模式为simple
100     fn exec_idle(service: &mut ServiceUnit) -> Result<(), RuntimeError> {
101         // 将该service加入等待运行队列
102         let _ = service.set_attr(Segment::Service, "Type", "simple");
103         UnitManager::push_a_idle_service(service.unit_id());
104         Ok(())
105     }
106 
107     fn exec_notify(_service: &ServiceUnit) -> Result<(), RuntimeError> {
108         Ok(())
109     }
110 
111     fn exec_one_shot(_service: &ServiceUnit) -> Result<(), RuntimeError> {
112         Ok(())
113     }
114 
115     fn exec_start_pos(service: &ServiceUnit) -> Result<(), RuntimeError> {
116         let cmds = service.service_part().exec_start_pos();
117         for cmd in cmds {
118             cmd.spawn()?;
119         }
120         Ok(())
121     }
122 
123     fn exec_start_pre(service: &ServiceUnit) -> Result<(), RuntimeError> {
124         let cmds = service.service_part().exec_start_pre();
125         for cmd in cmds {
126             cmd.spawn()?;
127         }
128         Ok(())
129     }
130 
131     //显式停止时执行的命令
132     fn exec_stop(service: &mut ServiceUnit) -> Result<(), RuntimeError> {
133         let cmds = service.service_part().exec_stop();
134         for cmd in cmds {
135             cmd.no_spawn()?;
136         }
137         Ok(())
138     }
139 
140     //停止后执行的命令
141     fn exec_stop_post(service: &mut ServiceUnit) -> Result<(), RuntimeError> {
142         let cmds = service.mut_service_part().mut_exec_stop_post();
143         for cmd in cmds {
144             cmd.no_spawn()?;
145         }
146         Ok(())
147     }
148 
149     fn exec_reload(service: &mut ServiceUnit) -> Result<(), RuntimeError> {
150         let cmds = service.service_part().exec_reload();
151         for cmd in cmds {
152             cmd.no_spawn()?;
153         }
154         Ok(())
155     }
156 
157     /// ## 服务退出执行的逻辑(包括自然退出及显式退出)
158     pub fn after_exit(service: &mut ServiceUnit, exit_status: ExitStatus) {
159         //TODO: 需要考虑是否需要在此处执行退出后代码,还是只需要显式退出时才执行
160         let _ = Self::exec_stop_post(service);
161 
162         // 停止被spawn的命令
163         let s_part = service.mut_service_part();
164         for cmd in s_part.mut_exec_start_pos() {
165             cmd.stop()
166         }
167         for cmd in s_part.mut_exec_start_pre() {
168             cmd.stop()
169         }
170 
171         // 取消未进行的定时器任务
172         TimerManager::cancel_timer(service.unit_id());
173 
174         // 关闭和此服务绑定的项目
175         for bind in service.unit_base().unit_part().be_binded_by() {
176             UnitManager::kill_running(*bind);
177         }
178 
179         //判断是否需要restart,需要则再次启动服务
180         if service.service_part().restart().is_restart(&exit_status) {
181             let ns = service.service_part().restart_sec();
182             let binds = service.unit_base().unit_part().be_binded_by();
183             let binds = Vec::from(binds);
184             let id = service.unit_id();
185             if ns > 0 {
186                 let cmds = service.service_part().exec_reload().clone();
187                 TimerManager::push_timer(
188                     Duration::from_nanos(ns),
189                     move || {
190                         for cmd in &cmds {
191                             cmd.no_spawn()?;
192                         }
193                         Executor::exec(id)?;
194                         for bind in &binds {
195                             Executor::exec(*bind)?
196                         }
197                         Ok(())
198                     },
199                     service.unit_id(),
200                 )
201             } else {
202                 let _ = Self::exec_reload(service);
203                 let _ = Executor::exec(id);
204             }
205             return;
206         }
207 
208         //如果该进程标记了RemainAfterExit,则将其加入特殊标记表
209         if service.service_part().remain_after_exit() {
210             UnitManager::push_flag_running(service.unit_id());
211             return;
212         }
213 
214         //停止服务后设置Unit状态
215         service.mut_unit_base().set_state(UnitState::Disabled);
216     }
217 
218     /// ## 显示退出Service
219     pub fn exit(service: &mut ServiceUnit) {
220         // TODO: 打印日志
221         let _ = Self::exec_stop(service);
222 
223         let ns = service.service_part().timeout_stop_sec();
224         let id = service.unit_id();
225         if ns != 0 {
226             // 计时器触发后若服务还未停止,则kill掉进程
227             TimerManager::push_timer(
228                 Duration::from_nanos(ns),
229                 move || {
230                     if UnitManager::is_running_unit(&id) {
231                         UnitManager::kill_running(id);
232                     }
233                     Ok(())
234                 },
235                 service.unit_id(),
236             )
237         }
238     }
239 }
240