| 33 | |
| 34 | #[pyfunction] |
| 35 | fn fork_exec(args: ForkExecArgs<'_>, vm: &VirtualMachine) -> PyResult<libc::pid_t> { |
| 36 | // Check for interpreter shutdown when preexec_fn is used |
| 37 | if args.preexec_fn.is_some() |
| 38 | && vm |
| 39 | .state |
| 40 | .finalizing |
| 41 | .load(core::sync::atomic::Ordering::Acquire) |
| 42 | { |
| 43 | return Err(vm.new_python_finalization_error( |
| 44 | "preexec_fn not supported at interpreter shutdown".to_owned(), |
| 45 | )); |
| 46 | } |
| 47 | |
| 48 | let extra_groups = args |
| 49 | .groups_list |
| 50 | .as_ref() |
| 51 | .map(|l| Vec::<Gid>::try_from_borrowed_object(vm, l.as_object())) |
| 52 | .transpose()?; |
| 53 | let argv = CharPtrVec::from_iter(args.args.iter()); |
| 54 | let envp = args.env_list.as_ref().map(CharPtrVec::from_iter); |
| 55 | let procargs = ProcArgs { |
| 56 | argv: &argv, |
| 57 | envp: envp.as_deref(), |
| 58 | extra_groups: extra_groups.as_deref(), |
| 59 | }; |
| 60 | match unsafe { nix::unistd::fork() }.map_err(|err| err.into_pyexception(vm))? { |
| 61 | nix::unistd::ForkResult::Child => exec(&args, procargs, vm), |
| 62 | nix::unistd::ForkResult::Parent { child } => Ok(child.as_raw()), |
| 63 | } |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | macro_rules! gen_args { |