What happens is I need to catch the return type of this call and use .wait() or .wait_with_output()
It seems like it waits until the process is zombie or terminated, but it's always zombie, I tried to run a simple Python code as the comment & it seems like Rust hold the process zombie,
So I tried to detach the process like this:
But it seems like Rust still hold the child process captive as zombie,
I would like to let my child process terminated and catch on terminated only because I can manually in runtime change the status of the child process status to zombie for debug purposes and I don't want my Rust runtime to end (You can't differentiate between zombie status of ended run or manually triggered by the user)
Any clues how can I achieve that?
On Unix an exitted process will remain in zombie state until it's parent process waits on it. When the parent process exits, the parent process of the child gets set to the reaper, which is generally init. Init automatically awaits every zombie process. So basically what you did have to do to avoid dealing with zombie processes is either to spawn a process which in turn spawns the intended child process and immediately after that exits. Or to register a SIGCHLD handler and wait on zombie processes when it fires.
The immediate reason why this doesn't work is that you need to tell the shell to not wait for the command to finish, by running command &, like
let mut bg_cmd = command.to_owned();
bg_cmd.push('&');
Command::new(bg_cmd)...
but this will have other problems:
If the command could ever contain unexpected spaces, the shell command will be wrong, and at best it will fail; at worst, you’ll have a trivially remotely exploitable security issue.
spawn() could succeed but the shell could get an error, so you should really be using .output() instead of .spawn(), and not setting .stdin(), .stdout() and .stderr(). (Maybe .stdin() should be Stdio::null().)
However, not using sh -c and following bjorn3’s or Alice’s advice, or even just calling .try_wait() regularly, would be much safer and more maintainable in the end.
If I've process that has child process which runs the original child I would've wanted,
the middle process will stay running until his child process is done and then that child will be zombie, only once that middle process will get zombie only then everything will be terminated,
even If I can make the middle process return it's child PID to my code and I will never wait to the middle process it will stay zombie until my process is terminated,
I've no clue how to do what you meant by SIGCHLD and AI is no help here, if you can elaborate I would love that
the issue is wait is capturing on zombie and not letting the child process terminate, I can't differentiate if my child process has zombiefied because of it being done running or someone manually stopped my process
I don't really know what you mean by that. Processes turn into zombies only in one situation: the parent process has not yet released it. You release it by calling wait. There should not be a problem.
So that is not my full issue here,
Because wait is waiting for zombie or terminated status I can't tell of my child process was zombie because it finished to run or because someone interrupted and stopped my child process,
The OS can't tell why it was zombified but as long as the parent exists the child process will never be terminated, so I would guess the only way to stop having this issue is to fully detach child from parent that way I could use sysinfo and wait until terminated or can't get info about it,
I would lose my stdout, stderr & exit code of the child process but one thing after another.
You will have a lot of trouble telling whether your child process was killed or finished successfully if you run it via sh -c. However, if you run it directly then you can use the methods on ExitStatusExt to find out how it terminated.
Separately, stdout etc. pipes can survive an intermediate child terminating, but I don’t think that’s the right solution here anyway; it won’t be the usual way a program is run and its output captured.
You exit the middle process without waiting for the child process. This will reparent the child process to the init process (pid 1), which is guaranteed to reap zombie processes.