From: Bennet Bleßmann Date: Sun, 20 Jul 2025 22:06:03 +0000 (+0200) Subject: don't remove the child on wait/kill X-Git-Tag: v0.10.0~35^2^2~19 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=ca52c65902987b47d1fd392a2f81cd4529c5a431;p=scryer-prolog.git don't remove the child on wait/kill - important for wait with timout(0) as we may want to try again until the process has realy exited. - make process_release release the process instead --- diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 0c1320b1..346e68af 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -543,6 +543,8 @@ enum SystemClauseType { ProcessWait, #[strum_discriminants(strum(props(Arity = "1", Name = "$process_kill")))] ProcessKill, + #[strum_discriminants(strum(props(Arity = "1", Name = "$process_release")))] + ProcessRelease, #[strum_discriminants(strum(props(Arity = "1", Name = "$pid")))] Pid, #[strum_discriminants(strum(props(Arity = "4", Name = "$chars_base64")))] @@ -1834,6 +1836,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::CallProcessCreate | &Instruction::CallProcessWait | &Instruction::CallProcessKill | + &Instruction::CallProcessRelease | &Instruction::CallPid | &Instruction::CallCharsBase64 | &Instruction::CallDevourWhitespace | @@ -2075,6 +2078,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::ExecuteProcessCreate | &Instruction::ExecuteProcessWait | &Instruction::ExecuteProcessKill | + &Instruction::ExecuteProcessRelease | &Instruction::ExecutePid | &Instruction::ExecuteCharsBase64 | &Instruction::ExecuteDevourWhitespace | diff --git a/src/lib/process.pl b/src/lib/process.pl index b17b3224..358484c5 100644 --- a/src/lib/process.pl +++ b/src/lib/process.pl @@ -53,7 +53,9 @@ process_kill(Pid) :- must_be(integer, Pid), '$process_kill'(Pid). -process_release(Pid) :- process_wait(Pid, _). +process_release(Pid) :- + process_wait(Pid, _), + '$process_release'(Pid). must_be_known_options(_, _, []). diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 66133c3c..00396e23 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -4811,6 +4811,14 @@ impl Machine { try_or_throw!(self.machine_st, self.process_kill()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } + &Instruction::CallProcessRelease => { + try_or_throw!(self.machine_st, self.process_release()); + step_or_fail!(self, self.machine_st.p += 1); + } + &Instruction::ExecuteProcessRelease => { + try_or_throw!(self.machine_st, self.process_release()); + step_or_fail!(self, self.machine_st.p = self.machine_st.cp); + } &Instruction::CallPid => { self.pid(); step_or_fail!(self, self.machine_st.p += 1); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index f40a6cbc..a1eb15be 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -8498,13 +8498,14 @@ impl Machine { Ok(child) => { let pid = child.id(); + dbg!(pid); + self.machine_st.child_processes.insert(pid, child); - self.machine_st.bind( - pid_r - .as_var() - .expect("invalid values should have been rejected on the prolog side"), - fixnum_as_cell!(Fixnum::build_with(pid)), + unify!( + self.machine_st, + pid_r, + fixnum_as_cell!(Fixnum::build_with(pid)) ); Ok(()) @@ -8637,7 +8638,7 @@ impl Machine { .existence_error(ExistenceError::Process(pid_r)); return Err(self.machine_st.error_form(err, stub_gen())); }; - let Some(mut child) = self.machine_st.child_processes.remove(&pid) else { + let Some(child) = self.machine_st.child_processes.get_mut(&pid) else { let err = self .machine_st .existence_error(ExistenceError::Process(pid_r)); @@ -8679,7 +8680,6 @@ impl Machine { self.machine_st.throw_resource_error(resource_err_loc); } } - Ok(()) } else { #[cfg(unix)] { @@ -8687,7 +8687,7 @@ impl Machine { if let Some(signal) = ExitStatusExt::signal(&exit_status) { let mut writer = - Heap::functor_writer(functor!(atom!("signal"), [fixnum(signal)])); + Heap::functor_writer(functor!(atom!("killed"), [fixnum(signal)])); match writer(&mut self.machine_st.heap) { Ok(loc) => { @@ -8696,19 +8696,17 @@ impl Machine { Err(resource_err_loc) => { self.machine_st.throw_resource_error(resource_err_loc); } - }; - Ok(()) + } } else { unify!(self.machine_st, status_r, atom_as_cell!(atom!("unknown"))); - Ok(()) } } #[cfg(not(unix))] { unify!(self.machine_st, status_r, atom_as_cell!(atom!("unknown"))); - Ok(()) } } + Ok(()) } Err(_) => { let perm_error = self.machine_st.permission_error( @@ -8737,7 +8735,7 @@ impl Machine { .existence_error(ExistenceError::Process(pid_r)); return Err(self.machine_st.error_form(err, stub_gen())); }; - let Some(mut child) = self.machine_st.child_processes.remove(&pid) else { + let Some(child) = self.machine_st.child_processes.get_mut(&pid) else { let err = self .machine_st .existence_error(ExistenceError::Process(pid_r)); @@ -8752,6 +8750,25 @@ impl Machine { Ok(()) } + pub(crate) fn process_release(&mut self) -> CallResult { + fn stub_gen() -> Vec { + 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(()) + } + #[inline(always)] pub(crate) fn chars_base64(&mut self) -> CallResult { let padding = cell_as_atom!(self.deref_register(3));