get process_create working and add tests

This commit is contained in:
Bennet Bleßmann
2025-07-26 18:21:00 +02:00
committed by Bennet Bleßmann
parent 1120bcde29
commit dc08a4ab11
14 changed files with 223 additions and 91 deletions

View File

@@ -56,6 +56,7 @@ use std::net::{SocketAddr, ToSocketAddrs};
use std::net::{TcpListener, TcpStream};
use std::num::NonZeroU32;
use std::process;
use std::process::Child;
use std::process::Stdio;
#[cfg(feature = "http")]
use std::str::FromStr;
@@ -8496,16 +8497,13 @@ impl Machine {
match command.spawn() {
Ok(child) => {
let pid = child.id();
dbg!(pid);
self.machine_st.child_processes.insert(pid, child);
let child_process_alloc: TypedArenaPtr<Child> =
arena_alloc!(child, &mut self.machine_st.arena);
unify!(
self.machine_st,
pid_r,
fixnum_as_cell!(Fixnum::build_with(pid))
typed_arena_ptr_as_cell!(child_process_alloc)
);
Ok(())
@@ -8617,44 +8615,84 @@ impl Machine {
})
}
pub(crate) fn process_id(&mut self) -> CallResult {
fn stub_gen() -> Vec<FunctorElement> {
functor_stub(atom!("process_id"), 2)
}
// Process
let process_r = self.deref_register(1);
// Pid
let pid_r = self.deref_register(2);
let Some(ptr) = process_r.to_untyped_arena_ptr() else {
let err = self.machine_st.type_error(ValidType::Process, process_r);
return Err(self.machine_st.error_form(err, stub_gen()));
};
let process = match_untyped_arena_ptr!(ptr,
(ArenaHeaderTag::ChildProcess, child_process) => {
child_process
}
(ArenaHeaderTag::Dropped, _dropped) => {
let err = self.machine_st.existence_error(ExistenceError::Process(process_r));
return Err(self.machine_st.error_form(err, stub_gen()));
}
_ => {
let err = self.machine_st.type_error(ValidType::Process, process_r);
return Err(self.machine_st.error_form(err, stub_gen()));
}
);
self.machine_st.bind(
pid_r.as_var().unwrap(),
fixnum_as_cell!(Fixnum::build_with(process.id())),
);
Ok(())
}
pub(crate) fn process_wait(&mut self) -> CallResult {
fn stub_gen() -> Vec<FunctorElement> {
functor_stub(atom!("process_wait"), 2)
}
// Pid
let pid_r = self.deref_register(1);
// Process
let process_r = self.deref_register(1);
// Var | Status
let status_r = self.deref_register(2);
// timeout | 0
let timeout_r = self.deref_register(3);
let Some(pid) = pid_r
.to_fixnum()
.and_then(|elem| elem.get_num().try_into().ok())
else {
let err = self
.machine_st
.existence_error(ExistenceError::Process(pid_r));
return Err(self.machine_st.error_form(err, stub_gen()));
};
let Some(child) = self.machine_st.child_processes.get_mut(&pid) else {
let err = self
.machine_st
.existence_error(ExistenceError::Process(pid_r));
let Some(ptr) = process_r.to_untyped_arena_ptr() else {
let err = self.machine_st.type_error(ValidType::Process, process_r);
return Err(self.machine_st.error_form(err, stub_gen()));
};
let mut process = match_untyped_arena_ptr!(ptr,
(ArenaHeaderTag::ChildProcess, child_process) => {
child_process
}
(ArenaHeaderTag::Dropped, _dropped) => {
let err = self.machine_st.existence_error(ExistenceError::Process(process_r));
return Err(self.machine_st.error_form(err, stub_gen()));
}
_ => {
let err = self.machine_st.type_error(ValidType::Process, process_r);
return Err(self.machine_st.error_form(err, stub_gen()));
}
);
let status = if let Some(atom) = timeout_r.to_atom() {
match atom {
atom!("infinite") => child.wait().map(Some),
atom!("infinite") => process.wait().map(Some),
_ => {
panic!("Invalid Timeout value")
}
}
} else if let Some(timeout) = timeout_r.to_fixnum() {
if timeout.get_num() == 0 {
child.try_wait()
process.try_wait()
} else {
panic!("Invalid Timeout value")
}
@@ -8728,23 +8766,28 @@ impl Machine {
}
// Pid
let pid_r = self.deref_register(1);
let Some(pid) = pid_r
.to_fixnum()
.and_then(|elem| elem.get_num().try_into().ok())
else {
let err = self
.machine_st
.existence_error(ExistenceError::Process(pid_r));
let process_r = self.deref_register(1);
let Some(ptr) = process_r.to_untyped_arena_ptr() else {
let err = self.machine_st.type_error(ValidType::Process, process_r);
return Err(self.machine_st.error_form(err, stub_gen()));
};
let Some(child) = self.machine_st.child_processes.get_mut(&pid) else {
let err = self
.machine_st
.existence_error(ExistenceError::Process(pid_r));
return Err(self.machine_st.error_form(err, stub_gen()));
};
if child.kill().is_err() {
let mut process = match_untyped_arena_ptr!(ptr,
(ArenaHeaderTag::ChildProcess, child_process) => {
child_process
}
(ArenaHeaderTag::Dropped, _dropped) => {
let err = self.machine_st.existence_error(ExistenceError::Process(process_r));
return Err(self.machine_st.error_form(err, stub_gen()));
}
_ => {
let err = self.machine_st.type_error(ValidType::Process, process_r);
return Err(self.machine_st.error_form(err, stub_gen()));
}
);
if process.kill().is_err() {
let perm_error =
self.machine_st
.permission_error(Permission::Modify, atom!("process"), stub_gen());
@@ -8758,18 +8801,23 @@ impl Machine {
functor_stub(atom!("process_release"), 1)
}
let pid_r = self.deref_register(1);
let Some(pid) = pid_r
.to_fixnum()
.and_then(|elem| elem.get_num().try_into().ok())
else {
let err = self
.machine_st
.existence_error(ExistenceError::Process(pid_r));
return Err(self.machine_st.error_form(err, stub_gen()));
};
self.machine_st.child_processes.remove(&pid);
Ok(())
let process = self.deref_register(1);
if let Some(ptr) = process.to_untyped_arena_ptr() {
match_untyped_arena_ptr!(ptr,
(ArenaHeaderTag::ChildProcess, child_process) => {
child_process.drop_payload();
return Ok(());
}
_ => {
}
);
}
let err = self.machine_st.type_error(ValidType::Process, process);
Err(self.machine_st.error_form(err, stub_gen()))
}
#[inline(always)]