-
Notifications
You must be signed in to change notification settings - Fork 4
feat: update state machine for process #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Changes: - Fix the memory ordering issue in transition_to_zombie function, change from Relaxed to Release to achieve Acquire-Release ordering with zombie state setting and getting - Remove the state transition in exit function of a process, bring the transition to do_exit for single resposibility of reparenting children in exit - Add some comments on memory ordering
Changes: - Add WaitEventFlags bitflags to ThreadGroup - Add wait_events and last_stop_signal fields to ThreadGroup - Implement set_stop_signal, set_cont_signal on Process - Implement peek/consume methods for stop/continue events - Update ThreadGroup::default() to initialize new fields Rationale: Events persist until zombie reaping, ensuring proper WUNTRACED/WCONTINUED reporting
…waitpid" This reverts commit 2f2bb17.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces a state machine for process lifecycle management, replacing the simple boolean is_zombie flag with a three-state system (RUNNING, STOPPED, ZOMBIE). The implementation adds public getters for checking process states and transition methods for moving between states, with careful attention to atomic operations and memory ordering guarantees.
Key Changes
- Replaced
AtomicBool is_zombiewithAtomicU8 stateto support multiple process states - Added three state query methods (
is_running(),is_stopped(),is_zombie()) - Implemented atomic state transition methods with explicit memory ordering documentation
- Added
bitflagsdependency for ProcessState definition
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| src/process.rs | Introduced ProcessState bitflags, replaced is_zombie field with state field, added state query and transition methods, updated Process constructor to initialize with RUNNING state |
| Cargo.toml | Added bitflags dependency as workspace dependency |
Comments suppressed due to low confidence (1)
src/process.rs:329
- The
exit()method no longer transitions the process to the ZOMBIE state. The old code hadself.is_zombie.store(true, Ordering::Release);at line 320, which was removed but not replaced with a call toself.transition_to_zombie(). This will cause the process to remain in its current state after exit, breaking the expected behavior whereexit()should mark the process as a zombie (as tested intests/process.rs:20-21).
Add self.transition_to_zombie(); before or after the children are transferred to the reaper.
pub fn exit(self: &Arc<Self>) {
// TODO: child subreaper
let reaper = INIT_PROC.get().unwrap();
if Arc::ptr_eq(self, reaper) {
return;
}
let mut children = self.children.lock(); // Acquire the lock first
let mut reaper_children = reaper.children.lock();
let reaper = Arc::downgrade(reaper);
for (pid, child) in core::mem::take(&mut *children) {
*child.parent.lock() = reaper.clone();
reaper_children.insert(pid, child);
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Changes: - Remove PartialEq impl for ProcessState - Update process state comparison functions to use bitflags contains function - Update transition_to_x function logic for state safety
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/process.rs:330
- The
exit()method no longer transitions the process to the ZOMBIE state. The old code hadself.is_zombie.store(true, Ordering::Release)at line 321, which was removed but not replaced with a call toself.transition_to_zombie(). This breaks the expected behavior as shown in the test attests/process.rs:21which expectschild.is_zombie()to return true after callingexit().
Add self.transition_to_zombie(); after acquiring the children lock to maintain the correct state transition.
pub fn exit(self: &Arc<Self>) {
// TODO: child subreaper
let reaper = INIT_PROC.get().unwrap();
if Arc::ptr_eq(self, reaper) {
return;
}
let mut children = self.children.lock(); // Acquire the lock first
let mut reaper_children = reaper.children.lock();
let reaper = Arc::downgrade(reaper);
for (pid, child) in core::mem::take(&mut *children) {
*child.parent.lock() = reaper.clone();
reaper_children.insert(pid, child);
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…nd session test based on new state machine. Update cargo.toml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/process.rs:330
- The
exit()method no longer transitions the process to the ZOMBIE state, which breaks the typical process lifecycle semantics. Callers now need to explicitly calltransition_to_zombie()afterexit(), as seen throughout the test changes. Consider either:
- Having
exit()automatically calltransition_to_zombie()at the end, or - Renaming
exit()to clarify it doesn't mark the process as a zombie (e.g.,reparent_children())
The current API design is error-prone since forgetting to call transition_to_zombie() after exit() would leave the process in an inconsistent state.
/// Terminates the [`Process`].
///
/// Child processes are inherited by the init process or by the nearest
/// subreaper process.
///
/// This method panics if the [`Process`] is the init process.
pub fn exit(self: &Arc<Self>) {
// TODO: child subreaper
let reaper = INIT_PROC.get().unwrap();
if Arc::ptr_eq(self, reaper) {
return;
}
let mut children = self.children.lock(); // Acquire the lock first
let mut reaper_children = reaper.children.lock();
let reaper = Arc::downgrade(reaper);
for (pid, child) in core::mem::take(&mut *children) {
*child.parent.lock() = reaper.clone();
reaper_children.insert(pid, child);
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (2)
src/process.rs:312
- The documentation comment for
exit()should be updated to clarify that this method does NOT transition the process to zombie state anymore (as indicated by the removal of the "marking it as a zombie process" phrase). Consider adding: "Note: This method does not change the process state. Callers should calltransition_to_zombie()to mark the process as a zombie after calling this method."
/// Terminates the [`Process`].
///
/// Child processes are inherited by the init process or by the nearest
/// subreaper process.
///
/// This method panics if the [`Process`] is the init process.
src/process.rs:330
- The
exit()method no longer transitions the process to ZOMBIE state (the previousis_zombie.store(true, Ordering::Release)call was removed). This is a breaking API change that requires callers to explicitly calltransition_to_zombie()afterexit(). Consider either:
- Keeping the automatic zombie transition in
exit()for backward compatibility, or - Renaming this method (e.g., to
reparent_children()) to better reflect its purpose and make the breaking change more obvious, or - At minimum, updating the documentation to clearly state that callers must call
transition_to_zombie()after this method.
/// Terminates the [`Process`].
///
/// Child processes are inherited by the init process or by the nearest
/// subreaper process.
///
/// This method panics if the [`Process`] is the init process.
pub fn exit(self: &Arc<Self>) {
// TODO: child subreaper
let reaper = INIT_PROC.get().unwrap();
if Arc::ptr_eq(self, reaper) {
return;
}
let mut children = self.children.lock(); // Acquire the lock first
let mut reaper_children = reaper.children.lock();
let reaper = Arc::downgrade(reaper);
for (pid, child) in core::mem::take(&mut *children) {
*child.parent.lock() = reaper.clone();
reaper_children.insert(pid, child);
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ProcessState::from_bits_truncate(bits).contains(ProcessState::STOPPED) | ||
| } | ||
|
|
||
| /// Change the [`Process`] from `Running` to `Stopped`. |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The documentation says "Change the [Process] from Running to Stopped" but the implementation allows transitioning from any non-ZOMBIE state that has RUNNING set to STOPPED. The documentation should clarify that this is not strictly a RUNNING -> STOPPED transition but rather "sets the process to STOPPED state if it's currently RUNNING and not ZOMBIE". Consider updating to: "Transitions the [Process] to Stopped state."
| /// Change the [`Process`] from `Running` to `Stopped`. | |
| /// Transitions the [`Process`] to `Stopped` state. |
| ); | ||
| } | ||
|
|
||
| /// Change the [`Process`] from `Stopped` to `Running`. |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Similar to transition_to_stopped, the documentation says "Change the [Process] from Stopped to Running" but should more accurately reflect what the method does. Consider: "Transitions the [Process] to Running state."
| /// Change the [`Process`] from `Stopped` to `Running`. | |
| /// Transitions the [`Process`] to `Running` state. |
Changes:
src/process.rs, introduce the state machine for a process, including three states:RUNNING,STOPPED, andZOMBIE.