xref: /DragonOS/kernel/src/process/exit.rs (revision bf4a48994a2b284ee34aa49a66b4dec1b6ebc07c)
1*bf4a4899SLoGin use core::intrinsics::likely;
2*bf4a4899SLoGin 
3*bf4a4899SLoGin use alloc::sync::Arc;
4*bf4a4899SLoGin 
5*bf4a4899SLoGin use crate::{
6*bf4a4899SLoGin     arch::{
7*bf4a4899SLoGin         ipc::signal::{SigChildCode, Signal},
8*bf4a4899SLoGin         sched::sched,
9*bf4a4899SLoGin         CurrentIrqArch,
10*bf4a4899SLoGin     },
11*bf4a4899SLoGin     exception::InterruptArch,
12*bf4a4899SLoGin     syscall::{user_access::UserBufferWriter, SystemError},
13*bf4a4899SLoGin };
14*bf4a4899SLoGin 
15*bf4a4899SLoGin use super::{
16*bf4a4899SLoGin     abi::WaitOption, pid::PidType, resource::RUsage, Pid, ProcessControlBlock, ProcessManager,
17*bf4a4899SLoGin     ProcessState,
18*bf4a4899SLoGin };
19*bf4a4899SLoGin 
20*bf4a4899SLoGin /// 内核wait4时的参数
21*bf4a4899SLoGin #[derive(Debug)]
22*bf4a4899SLoGin pub struct KernelWaitOption<'a> {
23*bf4a4899SLoGin     pub pid_type: PidType,
24*bf4a4899SLoGin     pub pid: Pid,
25*bf4a4899SLoGin     pub options: WaitOption,
26*bf4a4899SLoGin     pub ret_status: i32,
27*bf4a4899SLoGin     pub ret_info: Option<WaitIdInfo>,
28*bf4a4899SLoGin     pub ret_rusage: Option<&'a mut RUsage>,
29*bf4a4899SLoGin     pub no_task_error: Option<SystemError>,
30*bf4a4899SLoGin }
31*bf4a4899SLoGin 
32*bf4a4899SLoGin #[derive(Debug, Clone)]
33*bf4a4899SLoGin pub struct WaitIdInfo {
34*bf4a4899SLoGin     pub pid: Pid,
35*bf4a4899SLoGin     pub status: i32,
36*bf4a4899SLoGin     pub cause: i32,
37*bf4a4899SLoGin }
38*bf4a4899SLoGin 
39*bf4a4899SLoGin impl<'a> KernelWaitOption<'a> {
40*bf4a4899SLoGin     pub fn new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self {
41*bf4a4899SLoGin         Self {
42*bf4a4899SLoGin             pid_type,
43*bf4a4899SLoGin             pid,
44*bf4a4899SLoGin             options,
45*bf4a4899SLoGin             ret_status: 0,
46*bf4a4899SLoGin             ret_info: None,
47*bf4a4899SLoGin             ret_rusage: None,
48*bf4a4899SLoGin             no_task_error: None,
49*bf4a4899SLoGin         }
50*bf4a4899SLoGin     }
51*bf4a4899SLoGin }
52*bf4a4899SLoGin 
53*bf4a4899SLoGin pub fn kernel_wait4(
54*bf4a4899SLoGin     mut pid: i64,
55*bf4a4899SLoGin     wstatus_buf: Option<UserBufferWriter<'_>>,
56*bf4a4899SLoGin     options: WaitOption,
57*bf4a4899SLoGin     rusage_buf: Option<&mut RUsage>,
58*bf4a4899SLoGin ) -> Result<usize, SystemError> {
59*bf4a4899SLoGin     // i64::MIN is not defined
60*bf4a4899SLoGin     if pid == i64::MIN {
61*bf4a4899SLoGin         return Err(SystemError::ESRCH);
62*bf4a4899SLoGin     }
63*bf4a4899SLoGin 
64*bf4a4899SLoGin     // 判断pid类型
65*bf4a4899SLoGin     let pidtype: PidType;
66*bf4a4899SLoGin 
67*bf4a4899SLoGin     if pid == -1 {
68*bf4a4899SLoGin         pidtype = PidType::MAX;
69*bf4a4899SLoGin     } else if pid < 0 {
70*bf4a4899SLoGin         pidtype = PidType::PGID;
71*bf4a4899SLoGin         kwarn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
72*bf4a4899SLoGin         pid = -pid;
73*bf4a4899SLoGin     } else if pid == 0 {
74*bf4a4899SLoGin         pidtype = PidType::PGID;
75*bf4a4899SLoGin         kwarn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
76*bf4a4899SLoGin         pid = ProcessManager::current_pcb().pid().data() as i64;
77*bf4a4899SLoGin     } else {
78*bf4a4899SLoGin         pidtype = PidType::PID;
79*bf4a4899SLoGin     }
80*bf4a4899SLoGin 
81*bf4a4899SLoGin     let pid = Pid(pid as usize);
82*bf4a4899SLoGin 
83*bf4a4899SLoGin     // 构造参数
84*bf4a4899SLoGin     let mut kwo = KernelWaitOption::new(pidtype, pid, options);
85*bf4a4899SLoGin 
86*bf4a4899SLoGin     kwo.options.insert(WaitOption::WEXITED);
87*bf4a4899SLoGin     kwo.ret_rusage = rusage_buf;
88*bf4a4899SLoGin 
89*bf4a4899SLoGin     // 调用do_wait,执行等待
90*bf4a4899SLoGin     let r = do_wait(&mut kwo)?;
91*bf4a4899SLoGin 
92*bf4a4899SLoGin     // 如果有wstatus_buf,则将wstatus写入用户空间
93*bf4a4899SLoGin     if let Some(mut wstatus_buf) = wstatus_buf {
94*bf4a4899SLoGin         let wstatus = if let Some(ret_info) = &kwo.ret_info {
95*bf4a4899SLoGin             ret_info.status
96*bf4a4899SLoGin         } else {
97*bf4a4899SLoGin             kwo.ret_status
98*bf4a4899SLoGin         };
99*bf4a4899SLoGin         wstatus_buf.copy_one_to_user(&wstatus, 0)?;
100*bf4a4899SLoGin     }
101*bf4a4899SLoGin 
102*bf4a4899SLoGin     return Ok(r);
103*bf4a4899SLoGin }
104*bf4a4899SLoGin 
105*bf4a4899SLoGin /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/exit.c#1573
106*bf4a4899SLoGin fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
107*bf4a4899SLoGin     let mut retval: Result<usize, SystemError>;
108*bf4a4899SLoGin     // todo: 在signal struct里面增加等待队列,并在这里初始化子进程退出的回调,使得子进程退出时,能唤醒当前进程。
109*bf4a4899SLoGin 
110*bf4a4899SLoGin     loop {
111*bf4a4899SLoGin         kwo.no_task_error = Some(SystemError::ECHILD);
112*bf4a4899SLoGin         let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD);
113*bf4a4899SLoGin         if kwo.pid_type != PidType::MAX && child_pcb.is_err() {
114*bf4a4899SLoGin             if let Some(err) = &kwo.no_task_error {
115*bf4a4899SLoGin                 retval = Err(err.clone());
116*bf4a4899SLoGin             } else {
117*bf4a4899SLoGin                 retval = Ok(0);
118*bf4a4899SLoGin             }
119*bf4a4899SLoGin 
120*bf4a4899SLoGin             if !kwo.options.contains(WaitOption::WNOHANG) {
121*bf4a4899SLoGin                 retval = Err(SystemError::ERESTARTSYS);
122*bf4a4899SLoGin                 if ProcessManager::current_pcb()
123*bf4a4899SLoGin                     .sig_info_irqsave()
124*bf4a4899SLoGin                     .sig_pending()
125*bf4a4899SLoGin                     .has_pending()
126*bf4a4899SLoGin                     == false
127*bf4a4899SLoGin                 {
128*bf4a4899SLoGin                     // todo: 增加子进程退出的回调后,这里可以直接等待在自身的child_wait等待队列上。
129*bf4a4899SLoGin                     continue;
130*bf4a4899SLoGin                 } else {
131*bf4a4899SLoGin                     break;
132*bf4a4899SLoGin                 }
133*bf4a4899SLoGin             } else {
134*bf4a4899SLoGin                 break;
135*bf4a4899SLoGin             }
136*bf4a4899SLoGin         }
137*bf4a4899SLoGin 
138*bf4a4899SLoGin         if kwo.pid_type == PidType::PID {
139*bf4a4899SLoGin             let child_pcb = child_pcb.unwrap();
140*bf4a4899SLoGin             // 获取weak引用,以便于在do_waitpid中能正常drop pcb
141*bf4a4899SLoGin             let child_weak = Arc::downgrade(&child_pcb);
142*bf4a4899SLoGin             let r = do_waitpid(child_pcb, kwo);
143*bf4a4899SLoGin             if r.is_some() {
144*bf4a4899SLoGin                 return r.unwrap();
145*bf4a4899SLoGin             } else {
146*bf4a4899SLoGin                 child_weak.upgrade().unwrap().wait_queue.sleep();
147*bf4a4899SLoGin             }
148*bf4a4899SLoGin         } else if kwo.pid_type == PidType::MAX {
149*bf4a4899SLoGin             // 等待任意子进程
150*bf4a4899SLoGin             // todo: 这里有问题!如果正在for循环的过程中,子进程退出了,可能会导致父进程永远等待。
151*bf4a4899SLoGin             let current_pcb = ProcessManager::current_pcb();
152*bf4a4899SLoGin             let rd_childen = current_pcb.children.read();
153*bf4a4899SLoGin             let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
154*bf4a4899SLoGin             for pid in rd_childen.iter() {
155*bf4a4899SLoGin                 let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
156*bf4a4899SLoGin                 if pcb.sched_info().state().is_exited() {
157*bf4a4899SLoGin                     kwo.ret_status = pcb.sched_info().state().exit_code().unwrap() as i32;
158*bf4a4899SLoGin                     drop(pcb);
159*bf4a4899SLoGin                     unsafe { ProcessManager::release(pid.clone()) };
160*bf4a4899SLoGin                     return Ok(pid.clone().into());
161*bf4a4899SLoGin                 } else {
162*bf4a4899SLoGin                     unsafe { pcb.wait_queue.sleep_without_schedule() };
163*bf4a4899SLoGin                 }
164*bf4a4899SLoGin             }
165*bf4a4899SLoGin             drop(irq_guard);
166*bf4a4899SLoGin             sched();
167*bf4a4899SLoGin         } else {
168*bf4a4899SLoGin             // todo: 对于pgid的处理
169*bf4a4899SLoGin             kwarn!("kernel_wait4: currently not support {:?}", kwo.pid_type);
170*bf4a4899SLoGin             return Err(SystemError::EINVAL);
171*bf4a4899SLoGin         }
172*bf4a4899SLoGin     }
173*bf4a4899SLoGin 
174*bf4a4899SLoGin     return retval;
175*bf4a4899SLoGin }
176*bf4a4899SLoGin 
177*bf4a4899SLoGin fn do_waitpid(
178*bf4a4899SLoGin     child_pcb: Arc<ProcessControlBlock>,
179*bf4a4899SLoGin     kwo: &mut KernelWaitOption,
180*bf4a4899SLoGin ) -> Option<Result<usize, SystemError>> {
181*bf4a4899SLoGin     let state = child_pcb.sched_info().state();
182*bf4a4899SLoGin     // 获取退出码
183*bf4a4899SLoGin     match state {
184*bf4a4899SLoGin         ProcessState::Runnable => {
185*bf4a4899SLoGin             if kwo.options.contains(WaitOption::WNOHANG)
186*bf4a4899SLoGin                 || kwo.options.contains(WaitOption::WNOWAIT)
187*bf4a4899SLoGin             {
188*bf4a4899SLoGin                 if let Some(info) = &mut kwo.ret_info {
189*bf4a4899SLoGin                     *info = WaitIdInfo {
190*bf4a4899SLoGin                         pid: child_pcb.pid(),
191*bf4a4899SLoGin                         status: Signal::SIGCONT as i32,
192*bf4a4899SLoGin                         cause: SigChildCode::Continued.into(),
193*bf4a4899SLoGin                     };
194*bf4a4899SLoGin                 } else {
195*bf4a4899SLoGin                     kwo.ret_status = 0xffff;
196*bf4a4899SLoGin                 }
197*bf4a4899SLoGin 
198*bf4a4899SLoGin                 return Some(Ok(0));
199*bf4a4899SLoGin             }
200*bf4a4899SLoGin         }
201*bf4a4899SLoGin         ProcessState::Blocked(_) | ProcessState::Stopped => {
202*bf4a4899SLoGin             // todo: 在stopped里面,添加code字段,表示停止的原因
203*bf4a4899SLoGin             let exitcode = 0;
204*bf4a4899SLoGin             // 由于目前不支持ptrace,因此这个值为false
205*bf4a4899SLoGin             let ptrace = false;
206*bf4a4899SLoGin 
207*bf4a4899SLoGin             if (!ptrace) && (!kwo.options.contains(WaitOption::WUNTRACED)) {
208*bf4a4899SLoGin                 kwo.ret_status = 0;
209*bf4a4899SLoGin                 return Some(Ok(0));
210*bf4a4899SLoGin             }
211*bf4a4899SLoGin 
212*bf4a4899SLoGin             if likely(!(kwo.options.contains(WaitOption::WNOWAIT))) {
213*bf4a4899SLoGin                 kwo.ret_status = (exitcode << 8) | 0x7f;
214*bf4a4899SLoGin             }
215*bf4a4899SLoGin             if let Some(infop) = &mut kwo.ret_info {
216*bf4a4899SLoGin                 *infop = WaitIdInfo {
217*bf4a4899SLoGin                     pid: child_pcb.pid(),
218*bf4a4899SLoGin                     status: exitcode,
219*bf4a4899SLoGin                     cause: SigChildCode::Stopped.into(),
220*bf4a4899SLoGin                 };
221*bf4a4899SLoGin             }
222*bf4a4899SLoGin 
223*bf4a4899SLoGin             return Some(Ok(child_pcb.pid().data()));
224*bf4a4899SLoGin         }
225*bf4a4899SLoGin         ProcessState::Exited(status) => {
226*bf4a4899SLoGin             let pid = child_pcb.pid();
227*bf4a4899SLoGin             // kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid);
228*bf4a4899SLoGin 
229*bf4a4899SLoGin             if likely(!kwo.options.contains(WaitOption::WEXITED)) {
230*bf4a4899SLoGin                 return None;
231*bf4a4899SLoGin             }
232*bf4a4899SLoGin 
233*bf4a4899SLoGin             // todo: 增加对线程组的group leader的处理
234*bf4a4899SLoGin 
235*bf4a4899SLoGin             if let Some(infop) = &mut kwo.ret_info {
236*bf4a4899SLoGin                 *infop = WaitIdInfo {
237*bf4a4899SLoGin                     pid,
238*bf4a4899SLoGin                     status: status as i32,
239*bf4a4899SLoGin                     cause: SigChildCode::Exited.into(),
240*bf4a4899SLoGin                 };
241*bf4a4899SLoGin             }
242*bf4a4899SLoGin 
243*bf4a4899SLoGin             kwo.ret_status = status as i32;
244*bf4a4899SLoGin 
245*bf4a4899SLoGin             drop(child_pcb);
246*bf4a4899SLoGin             // kdebug!("wait4: to release {pid:?}");
247*bf4a4899SLoGin             unsafe { ProcessManager::release(pid) };
248*bf4a4899SLoGin             return Some(Ok(pid.into()));
249*bf4a4899SLoGin         }
250*bf4a4899SLoGin     };
251*bf4a4899SLoGin 
252*bf4a4899SLoGin     return None;
253*bf4a4899SLoGin }
254