Hey, I am running a program through System.cmd that does not mind its stdin being closed. The System.cmd documentation points me to the recommended wrapper script on the Port docs for preventing zombie processes, but this script accomplishes its task at the cost of ignoring when the wrapped program exits
#!/bin/bash
"$@" & # There is nothing making the script exit with this process exits
pid=$!
while read line ; do
:
done
kill -KILL $pid
Erlang/OTP 22 [erts-10.4.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]
Elixir 1.9.0 (compiled with Erlang/OTP 22)
Mac OS 10.14.5
System.cmd("/path/to/wrapper", ~w(echo test))
Hangs indefinitely even after echo test is run
The script should prevent zombie processes by exiting on stdin close, but also exit when the wrapped program finishes (preferably with the same exit code)
Thank you. I will add a note that the above should only be used if you expect the child program to run forever, for something that you expect to terminate, then it won't work (which is less of a problem because it will terminate eventtually). If anyone can come up with a different script for those cases or one that works for both, please let us know!
Also If anyone can come up with a script that is POSIX compliant, it will be greatly appreciated as this is the only piece of shell script code that is not
If you don't mind a port program made in C wrapping it the https://github.com/saleyn/erlexec (and erlang) library is what I've replaced my old scripts with. Otherwise I have a posix script on the ElixirForums somewhere in my old posts that I used to use that worked. I really recommend erlexec when you can though.
EDIT1: It's docs are at: http://saleyn.github.io/erlexec/
Similar interface to System.cmd but with more options, and the ability to send signals, kill it, etc... etc... Basically everything you'd ever need.
EDIT2: It's on hex at https://hex.pm/packages/erlexec too for note.
@josevalim The process I am running is ffmpeg... so yes, it will terminate eventually
@eksperimental I don't see anything non-POSIX other than the shebang, in which case I agree
@OvermindDL1 Thanks, this seems to be more than appropriate for my use case
Fantastic, thanks everyone for the input.
Ok, so I was able to write a version of the wrapper that terminates if the program terminates, at the cost of an extra process:
#!/bin/sh
# Start the program in the background
exec "$@" &
pid1=$!
# Silence warnings from here on
exec >/dev/null 2>&1
# Read from stdin in the background and
# kill running program when stdin closes
exec 0<&0 $(
while read; do :; done
kill -KILL $pid1
) &
pid2=$!
# Clean up
wait $pid1
kill -KILL $pid1
kill -KILL $pid2
shellcheck validates it OK too.
@josevalim I found that terminating the script does not kill the exec "$@" &
$ ./wrapper sh -c 'sleep 6; echo test'
^C
$ # but the 'sleep 6; echo test' is still running (ironically zombified now)
Edit: I realize this is also an issue present in the original script
We are not trapping signals. You have to send a Ctrl+D to simulate closing
Jos茅 Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Director of R&D
Yeah that sounds fair.
Thank you
@josevalim Is there a reason why you're killing $pid1 after waiting for it?
Ah, good catch. I will remove it.
I'll stop annoying you after this but the return code of the wait is also not forwarded. I'm not sure if this was intended..
@Javyre do you know how to forward it?
@josevalim This works for me:
# Clean up
wait $pid1
ret=$?
kill -KILL $pid2
exit $ret
Do you want to submit a PR with the last two proposed changes? Otherwise I will do it. :)
No problem, I'll do it
Most helpful comment
If you don't mind a port program made in C wrapping it the https://github.com/saleyn/erlexec (and erlang) library is what I've replaced my old scripts with. Otherwise I have a posix script on the ElixirForums somewhere in my old posts that I used to use that worked. I really recommend
erlexecwhen you can though.EDIT1: It's docs are at: http://saleyn.github.io/erlexec/
Similar interface to
System.cmdbut with more options, and the ability to send signals, kill it, etc... etc... Basically everything you'd ever need.EDIT2: It's on hex at https://hex.pm/packages/erlexec too for note.