Skip to content

Commit 40f851b

Browse files
committed
Add signal handling to task manager and implement signal accumulator
1 parent d3d17fe commit 40f851b

File tree

3 files changed

+246
-0
lines changed

3 files changed

+246
-0
lines changed

Modules/Task/src/Manager.rs

+80
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ struct Task_internal_type {
2222
Group: Group_identifier_type,
2323
/// Environment variables of the task.
2424
Environment_variables: Vec<Environment_variable_type>,
25+
/// Signals
26+
Signals: Signal_accumulator_type,
2527
}
2628

2729
static Manager_instance: OnceLock<Manager_type> = OnceLock::new();
@@ -73,6 +75,7 @@ impl Manager_type {
7375
User: User_identifier_type::Root,
7476
Group: Group_identifier_type::Root,
7577
Environment_variables: vec![],
78+
Signals: Signal_accumulator_type::New(),
7679
};
7780

7881
Self::Register_task_internal(Task_identifier, Task_internal, &mut Inner.Tasks)
@@ -108,6 +111,7 @@ impl Manager_type {
108111
User: User_identifier_type::Root,
109112
Group: Group_identifier_type::Root,
110113
Environment_variables: vec![],
114+
Signals: Signal_accumulator_type::New(),
111115
};
112116

113117
if Inner
@@ -329,6 +333,7 @@ impl Manager_type {
329333
User,
330334
Group,
331335
Environment_variables,
336+
Signals: Signal_accumulator_type::New(),
332337
},
333338
&mut self.0.write()?.Tasks,
334339
)?;
@@ -551,6 +556,34 @@ impl Manager_type {
551556

552557
Ok(())
553558
}
559+
560+
pub fn Pop_signal(
561+
&self,
562+
Task_identifier: Task_identifier_type,
563+
) -> Result_type<Option<Signal_type>> {
564+
Ok(self
565+
.0
566+
.write()?
567+
.Tasks
568+
.get_mut(&Task_identifier)
569+
.ok_or(Error_type::Invalid_task_identifier)?
570+
.Signals
571+
.Pop())
572+
}
573+
574+
pub fn Peek_signal(
575+
&self,
576+
Task_identifier: Task_identifier_type,
577+
) -> Result_type<Option<Signal_type>> {
578+
Ok(self
579+
.0
580+
.write()?
581+
.Tasks
582+
.get_mut(&Task_identifier)
583+
.ok_or(Error_type::Invalid_task_identifier)?
584+
.Signals
585+
.Peek())
586+
}
554587
}
555588

556589
#[cfg(test)]
@@ -583,6 +616,8 @@ mod Tests {
583616
Test_set_user(Manager);
584617
println!("Run test : Test_set_group");
585618
Test_set_group(Manager);
619+
println!("Run test : Test_signal");
620+
Test_signal(Manager);
586621
}
587622

588623
fn Test_get_task_name(Manager: &Manager_type) {
@@ -666,6 +701,9 @@ mod Tests {
666701
.New_task(Task, "Task 3", None, move || {
667702
let Task = Get_instance().Get_current_task_identifier().unwrap();
668703

704+
Get_instance().Set_user(Task, User_identifier).unwrap();
705+
Get_instance().Set_group(Task, Group_identifier).unwrap();
706+
669707
assert_eq!(Get_instance().Get_user(Task).unwrap(), User_identifier);
670708
assert_eq!(Get_instance().Get_group(Task).unwrap(), Group_identifier);
671709

@@ -756,4 +794,46 @@ mod Tests {
756794

757795
assert_eq!(Manager.Get_group(Task).unwrap(), Group);
758796
}
797+
798+
fn Test_signal(Manager: &Manager_type) {
799+
let Task = Manager.Get_current_task_identifier().unwrap();
800+
801+
let _ = Manager
802+
.New_task(Task, "Task with signal", None, || {
803+
let Task = Get_instance().Get_current_task_identifier().unwrap();
804+
805+
Manager_type::Sleep(Duration::from_millis(10));
806+
807+
assert_eq!(
808+
Get_instance().Peek_signal(Task).unwrap(),
809+
Some(Signal_type::Hangup)
810+
);
811+
812+
assert_eq!(
813+
Get_instance().Pop_signal(Task).unwrap(),
814+
Some(Signal_type::Kill)
815+
);
816+
})
817+
.unwrap();
818+
819+
Get_instance()
820+
.0
821+
.write()
822+
.unwrap()
823+
.Tasks
824+
.get_mut(&Task)
825+
.unwrap()
826+
.Signals
827+
.Send(Signal_type::Kill);
828+
829+
Get_instance()
830+
.0
831+
.write()
832+
.unwrap()
833+
.Tasks
834+
.get_mut(&Task)
835+
.unwrap()
836+
.Signals
837+
.Send(Signal_type::Hangup);
838+
}
759839
}

Modules/Task/src/Signal.rs

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
use core::fmt::Debug;
2+
3+
/// POSIX signals enumeration
4+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5+
#[repr(u8)]
6+
pub enum Signal_type {
7+
/// Hangup detected on controlling terminal or death of controlling process (SIGHUP)
8+
Hangup = 0,
9+
/// Interrupt from keyboard (SIGINT)
10+
Interrupt,
11+
/// Quit from keyboard (SIGQUIT)
12+
Quit,
13+
/// Unused : Illegal Instruction (SIGILL)
14+
Illegal_instruction,
15+
/// Trace/breakpoint trap (SIGTRAP)
16+
Trap,
17+
/// Abort signal from abort(3) (SIGABRT)
18+
Abort,
19+
/// Bus error (bad memory access) (SIGBUS)
20+
Bus_error,
21+
/// Floating-point exception (SIGFPE)
22+
Floating_point_exception,
23+
/// Kill signal (SIGKILL)
24+
Kill,
25+
/// User-defined signal 1 (SIGUSR1)
26+
User_1,
27+
/// Invalid memory reference (SIGSEGV)
28+
Segmentation_fault,
29+
/// User-defined signal 2 (SIGUSR2)
30+
User_2,
31+
/// Broken pipe: write to pipe with no readers (SIGPIPE)
32+
Broken_pipe,
33+
/// Timer signal from alarm(2) (SIGALRM)
34+
Alarm,
35+
/// Termination signal (SIGTERM)
36+
Termination,
37+
/// Stack fault on coprocessor (unused) (SIGSTKFLT)
38+
Stack_fault,
39+
/// Child stopped or terminated (SIGCHLD)
40+
Child,
41+
/// Continue if stopped (SIGCONT)
42+
Continue,
43+
/// Stop process (SIGSTOP)
44+
Stop,
45+
/// Stop typed at terminal (SIGTSTP)
46+
Terminal_stop,
47+
/// Terminal input for background process (SIGTTIN)
48+
Terminal_input,
49+
/// Terminal output for background process (SIGTTOU)
50+
Terminal_output,
51+
/// Urgent condition on socket (4.2BSD) (SIGURG)
52+
Urgent,
53+
/// CPU time limit exceeded (4.2BSD) (SIGXCPU)
54+
Cpu_time_limit_exceeded,
55+
/// File size limit exceeded (4.2BSD) (SIGXFSZ)
56+
File_size_limit_exceeded,
57+
/// Virtual alarm clock (4.2BSD) (SIGVTALRM)
58+
Virtual_alarm,
59+
/// Profiling timer expired (SIGPROF)
60+
Profiling_timer_expired,
61+
/// Window resize signal (4.3BSD, Sun) (SIGWINCH)
62+
Window_resize,
63+
/// I/O now possible (4.2BSD) (SIGIO)
64+
IO_Possible,
65+
/// Power failure (System V) (SIGPWR)
66+
Power_failure,
67+
/// Bad system call (SVr4) (SIGSYS)
68+
Bad_system_call,
69+
}
70+
71+
impl Signal_type {
72+
pub const First: Self = Self::Hangup;
73+
pub const Last: Self = Self::Bad_system_call;
74+
75+
pub const fn Get_discriminant(&self) -> u8 {
76+
*self as u8
77+
}
78+
}
79+
80+
#[derive(Debug, Copy, Clone)]
81+
#[repr(transparent)]
82+
pub struct Signal_accumulator_type {
83+
Accumulator: u32,
84+
}
85+
86+
impl Signal_accumulator_type {
87+
pub const fn New() -> Self {
88+
Self { Accumulator: 0 }
89+
}
90+
91+
pub const fn Send(&mut self, Signal: Signal_type) {
92+
self.Accumulator |= 1 << Signal as u32;
93+
}
94+
95+
pub const fn Clear(&mut self, Signal: Signal_type) {
96+
self.Accumulator &= !(1 << Signal as u32);
97+
}
98+
99+
pub const fn Has_signal(&self, Signal: Signal_type) -> bool {
100+
self.Accumulator & (1 << Signal as u32) != 0
101+
}
102+
103+
pub fn Peek(&self) -> Option<Signal_type> {
104+
for Bit in Signal_type::First as u8..=Signal_type::Last as u8 {
105+
let Signal = unsafe { core::mem::transmute::<u8, Signal_type>(Bit) };
106+
107+
if self.Has_signal(Signal) {
108+
return Some(Signal);
109+
}
110+
}
111+
112+
None
113+
}
114+
115+
pub fn Pop(&mut self) -> Option<Signal_type> {
116+
if let Some(Signal) = self.Peek() {
117+
self.Clear(Signal);
118+
119+
Some(Signal)
120+
} else {
121+
None
122+
}
123+
}
124+
}
125+
126+
#[cfg(test)]
127+
mod Tests {
128+
use super::*;
129+
130+
#[test]
131+
fn Test_send_and_has_signal() {
132+
let mut acc = Signal_accumulator_type::New();
133+
acc.Send(Signal_type::Interrupt);
134+
assert!(acc.Has_signal(Signal_type::Interrupt));
135+
}
136+
137+
#[test]
138+
fn Test_clear_signal() {
139+
let mut acc = Signal_accumulator_type::New();
140+
acc.Send(Signal_type::Quit);
141+
acc.Clear(Signal_type::Quit);
142+
assert!(!acc.Has_signal(Signal_type::Quit));
143+
}
144+
145+
#[test]
146+
fn Test_peek_and_pop() {
147+
let mut acc = Signal_accumulator_type::New();
148+
acc.Send(Signal_type::Hangup);
149+
acc.Send(Signal_type::User_1);
150+
assert_eq!(acc.Peek(), Some(Signal_type::Hangup));
151+
assert_eq!(acc.Pop(), Some(Signal_type::Hangup));
152+
assert_eq!(acc.Peek(), Some(Signal_type::User_1));
153+
assert_eq!(acc.Pop(), Some(Signal_type::User_1));
154+
assert_eq!(acc.Pop(), None);
155+
}
156+
157+
#[test]
158+
fn Test_signal_discriminant() {
159+
assert_eq!(
160+
Signal_type::Power_failure.Get_discriminant(),
161+
Signal_type::Power_failure as u8
162+
);
163+
}
164+
}

Modules/Task/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
mod Environment_variable;
66
mod Error;
77
mod Manager;
8+
mod Signal;
89
mod Task;
910
mod Thread;
1011

@@ -14,6 +15,7 @@ pub mod Raw_rwlock;
1415
pub use Environment_variable::*;
1516
pub use Error::*;
1617
pub use Manager::*;
18+
pub use Signal::*;
1719

1820
pub use Task::*;
1921
use Thread::*;

0 commit comments

Comments
 (0)