@@ -19,16 +19,23 @@ pub struct TtyJobCtrlManager;
1919impl TtyJobCtrlManager {
2020 /// ### 设置当前进程的tty
2121 pub fn proc_set_tty ( tty : Arc < TtyCore > ) {
22- let core = tty. core ( ) ;
2322 let pcb = ProcessManager :: current_pcb ( ) ;
24-
25- let mut ctrl = core. contorl_info_irqsave ( ) ;
23+ let _job_control_guard = tty. core ( ) . job_control_lock ( ) . lock ( ) ;
24+ let _membership_guard = crate :: process:: pid:: pid_membership_lock ( ) ;
25+ if tty
26+ . core ( )
27+ . flags ( )
28+ . intersects ( super :: tty_core:: TtyFlag :: HUPPING | super :: tty_core:: TtyFlag :: HUPPED )
29+ {
30+ return ;
31+ }
32+ let mut ctrl = tty. core ( ) . contorl_info_irqsave ( ) ;
33+ let mut signal = pcb. sig_info_mut ( ) ;
34+ if !signal. is_session_leader || signal. tty ( ) . is_some ( ) || ctrl. session . is_some ( ) {
35+ return ;
36+ }
2637 ctrl. set_info_by_pcb ( pcb. clone ( ) ) ;
27-
28- drop ( ctrl) ;
29-
30- let mut singal = pcb. sig_info_mut ( ) ;
31- singal. set_tty ( Some ( tty. clone ( ) ) ) ;
38+ signal. set_tty ( Some ( tty. clone ( ) ) ) ;
3239 }
3340
3441 /// ### 清除进程的tty
@@ -44,10 +51,47 @@ impl TtyJobCtrlManager {
4451 wguard. set_tty ( None ) ;
4552 }
4653
47- pub fn remove_session_tty ( tty : & Arc < TtyCore > ) {
54+ pub fn remove_session_tty ( tty : & Arc < TtyCore > ) -> Option < Arc < Pid > > {
55+ let _job_control_guard = tty. core ( ) . job_control_lock ( ) . lock ( ) ;
56+ Self :: remove_session_tty_job_locked ( tty, None )
57+ }
58+
59+ pub ( crate ) fn remove_session_tty_job_locked (
60+ tty : & Arc < TtyCore > ,
61+ expected_sid : Option < & Arc < Pid > > ,
62+ ) -> Option < Arc < Pid > > {
63+ let _membership_guard = crate :: process:: pid:: pid_membership_lock ( ) ;
64+ Self :: remove_session_tty_locked ( tty, expected_sid)
65+ }
66+
67+ pub fn remove_session_tty_if_owner (
68+ tty : & Arc < TtyCore > ,
69+ expected_sid : & Arc < Pid > ,
70+ ) -> Option < Arc < Pid > > {
71+ let _job_control_guard = tty. core ( ) . job_control_lock ( ) . lock ( ) ;
72+ Self :: remove_session_tty_job_locked ( tty, Some ( expected_sid) )
73+ }
74+
75+ /// The caller must hold PID_MEMBERSHIP_LOCK.
76+ fn remove_session_tty_locked (
77+ tty : & Arc < TtyCore > ,
78+ expected_sid : Option < & Arc < Pid > > ,
79+ ) -> Option < Arc < Pid > > {
4880 let mut ctrl = tty. core ( ) . contorl_info_irqsave ( ) ;
49- ctrl. session = None ;
50- ctrl. pgid = None ;
81+ if expected_sid. is_some_and ( |expected| {
82+ ctrl. session
83+ . as_ref ( )
84+ . is_none_or ( |owner| !Arc :: ptr_eq ( owner, expected) )
85+ } ) {
86+ return None ;
87+ }
88+ let sid = ctrl. session . take ( ) ;
89+ let pgid = ctrl. pgid . take ( ) ;
90+ drop ( ctrl) ;
91+ if let Some ( sid) = sid {
92+ Self :: session_clear_tty_locked ( sid) ;
93+ }
94+ pgid
5195 }
5296
5397 /// ### 检查tty
@@ -125,18 +169,31 @@ impl TtyJobCtrlManager {
125169 // https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/tty/tty_jobctrl.c#tiocsctty
126170 fn tiocsctty ( real_tty : Arc < TtyCore > , arg : usize ) -> Result < usize , SystemError > {
127171 let current = ProcessManager :: current_pcb ( ) ;
128- let siginfo_guard = current. sig_info_irqsave ( ) ;
172+ let _job_control_guard = real_tty. core ( ) . job_control_lock ( ) . lock ( ) ;
173+ let _membership_guard = crate :: process:: pid:: pid_membership_lock ( ) ;
174+ if real_tty
175+ . core ( )
176+ . flags ( )
177+ . intersects ( super :: tty_core:: TtyFlag :: HUPPING | super :: tty_core:: TtyFlag :: HUPPED )
178+ {
179+ return Err ( SystemError :: EIO ) ;
180+ }
181+ let ( is_session_leader, current_tty) = {
182+ let siginfo = current. sig_info_irqsave ( ) ;
183+ ( siginfo. is_session_leader , siginfo. tty ( ) )
184+ } ;
129185
130186 // 只有会话首进程才能设置控制终端
131- if !siginfo_guard . is_session_leader {
187+ if !is_session_leader {
132188 return Err ( SystemError :: EPERM ) ;
133189 }
134190
191+ let current_session = current. task_session ( ) ;
192+
135193 // 如果当前进程已经有控制终端,则返回错误(除非是同一个tty且会话相同)
136- if let Some ( current_tty) = siginfo_guard. tty ( ) {
137- if Arc :: ptr_eq ( & current_tty, & real_tty)
138- && current. task_session ( ) == real_tty. core ( ) . contorl_info_irqsave ( ) . session
139- {
194+ if let Some ( current_tty) = current_tty {
195+ let tty_session = real_tty. core ( ) . contorl_info_irqsave ( ) . session . clone ( ) ;
196+ if Arc :: ptr_eq ( & current_tty, & real_tty) && current_session == tty_session {
140197 // 如果已经是当前tty且会话相同,直接返回成功
141198 return Ok ( 0 ) ;
142199 } else {
@@ -145,13 +202,11 @@ impl TtyJobCtrlManager {
145202 }
146203 }
147204
148- drop ( siginfo_guard) ;
149-
150- let tty_ctrl_guard = real_tty. core ( ) . contorl_info_irqsave ( ) ;
205+ let mut tty_ctrl_guard = real_tty. core ( ) . contorl_info_irqsave ( ) ;
151206
152207 if let Some ( ref sid) = tty_ctrl_guard. session {
153208 // 如果当前进程是会话首进程,且tty的会话是当前进程的会话,则允许设置
154- if current . task_session ( ) == Some ( sid. clone ( ) ) {
209+ if current_session == Some ( sid. clone ( ) ) {
155210 // 这是正常情况:会话首进程要设置自己会话的tty为控制终端
156211 } else {
157212 // tty被其他会话占用
@@ -161,16 +216,16 @@ impl TtyJobCtrlManager {
161216 if !cred. has_capability ( CAPFlags :: CAP_SYS_ADMIN ) {
162217 return Err ( SystemError :: EPERM ) ;
163218 }
164- Self :: session_clear_tty ( sid. clone ( ) ) ;
219+ Self :: session_clear_tty_locked ( sid. clone ( ) ) ;
165220 } else {
166221 return Err ( SystemError :: EPERM ) ;
167222 }
168223 }
169224 }
170225
226+ tty_ctrl_guard. set_info_by_pcb ( current. clone ( ) ) ;
227+ current. sig_info_mut ( ) . set_tty ( Some ( real_tty. clone ( ) ) ) ;
171228 drop ( tty_ctrl_guard) ;
172-
173- Self :: proc_set_tty ( real_tty) ;
174229 Ok ( 0 )
175230 }
176231
@@ -249,57 +304,31 @@ impl TtyJobCtrlManager {
249304 }
250305
251306 let current = ProcessManager :: current_pcb ( ) ;
252-
307+ let _job_control_guard = real_tty. core ( ) . job_control_lock ( ) . lock ( ) ;
308+ let _membership_guard = crate :: process:: pid:: pid_membership_lock ( ) ;
309+ let current_session = current. task_session ( ) ;
310+ let current_tty = current. sig_info_irqsave ( ) . tty ( ) ;
253311 let mut ctrl = real_tty. core ( ) . contorl_info_irqsave ( ) ;
254-
312+ if current_tty
313+ . as_ref ( )
314+ . is_none_or ( |tty| !Arc :: ptr_eq ( tty, & real_tty) )
315+ || ctrl. session != current_session
255316 {
256- // if current.sig_info_irqsave().tty().is_none()
257- // || !Arc::ptr_eq(
258- // ¤t.sig_info_irqsave().tty().clone().unwrap(),
259- // &real_tty,
260- // )
261- // || ctrl.session != current.task_session()
262- // {
263- // log::debug!("sss-2");
264- // return Err(SystemError::ENOTTY);
265- // }
266-
267- // 拆分判断条件以便调试
268- let current_tty = current. sig_info_irqsave ( ) . tty ( ) ;
269- let condition1 = current_tty. is_none ( ) ;
270-
271- let condition2 = if let Some ( ref tty) = current_tty {
272- !Arc :: ptr_eq ( tty, & real_tty)
273- } else {
274- false // 如果 tty 为 None,这个条件就不用检查了
275- } ;
276-
277- let condition3 = ctrl. session != current. task_session ( ) ;
278-
279- if condition1 || condition2 || condition3 {
280- if condition1 {
281- log:: debug!( "sss-2: 失败原因 - 当前进程没有关联的 tty" ) ;
282- } else if condition2 {
283- log:: debug!( "sss-2: 失败原因 - 当前进程的 tty 与目标 tty 不匹配" ) ;
284- } else if condition3 {
285- log:: debug!( "sss-2: 失败原因 - 会话不匹配" ) ;
286- }
287- return Err ( SystemError :: ENOTTY ) ;
288- }
317+ return Err ( SystemError :: ENOTTY ) ;
289318 }
319+
290320 let pgrp =
291321 ProcessManager :: find_vpid ( RawPid :: new ( pgrp_nr as usize ) ) . ok_or ( SystemError :: ESRCH ) ?;
292-
293- if Self :: session_of_pgrp ( & pgrp) != current. task_session ( ) {
322+ if Self :: session_of_pgrp_locked ( & pgrp) != current_session {
294323 return Err ( SystemError :: EPERM ) ;
295324 }
296-
297325 ctrl. pgid = Some ( pgrp) ;
298326
299327 return Ok ( 0 ) ;
300328 }
301329
302- fn session_of_pgrp ( pgrp : & Arc < Pid > ) -> Option < Arc < Pid > > {
330+ /// The caller must hold PID_MEMBERSHIP_LOCK.
331+ fn session_of_pgrp_locked ( pgrp : & Arc < Pid > ) -> Option < Arc < Pid > > {
303332 let mut p = pgrp. pid_task ( PidType :: PGID ) ;
304333 if p. is_none ( ) {
305334 // this should not be None
@@ -329,33 +358,28 @@ impl TtyJobCtrlManager {
329358 return Ok ( 0 ) ;
330359 }
331360
332- let sid = pcb. task_session ( ) ;
333- let tty_pgrp = real_tty. core ( ) . contorl_info_irqsave ( ) . pgid . clone ( ) ;
361+ let tty_pgrp = if let Some ( sid) = pcb. task_session ( ) {
362+ Self :: remove_session_tty_if_owner ( & real_tty, & sid)
363+ } else {
364+ Self :: proc_clear_tty ( & pcb) ;
365+ None
366+ } ;
334367
335368 if let Some ( pgrp) = tty_pgrp {
336369 let _ = crate :: ipc:: kill:: send_signal_to_pgid ( & pgrp, Signal :: SIGHUP ) ;
337370 let _ = crate :: ipc:: kill:: send_signal_to_pgid ( & pgrp, Signal :: SIGCONT ) ;
338371 }
339372
340- {
341- let mut ctrl = real_tty. core ( ) . contorl_info_irqsave ( ) ;
342- ctrl. session = None ;
343- ctrl. pgid = None ;
344- }
345-
346- if let Some ( sid) = sid {
347- Self :: session_clear_tty ( sid) ;
348- } else {
349- Self :: proc_clear_tty ( & pcb) ;
350- }
351-
352373 Ok ( 0 )
353374 }
354375
355- pub fn session_clear_tty ( sid : Arc < Pid > ) {
356- // 清除会话的tty
357- for task in sid. tasks_iter ( PidType :: SID ) {
358- TtyJobCtrlManager :: proc_clear_tty ( & task) ;
376+ /// The caller must hold PID_MEMBERSHIP_LOCK.
377+ fn session_clear_tty_locked ( sid : Arc < Pid > ) {
378+ let leaders: alloc:: vec:: Vec < _ > = sid. tasks_iter ( PidType :: SID ) . collect ( ) ;
379+ for leader in leaders {
380+ for task in ProcessManager :: thread_group_tasks_snapshot ( leader) {
381+ TtyJobCtrlManager :: proc_clear_tty ( & task) ;
382+ }
359383 }
360384 }
361385
0 commit comments