How do you kill an OS process that was opened with open_port on a brutal_kill?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

How do you kill an OS process that was opened with open_port on a brutal_kill?

Vans S
So far if I use open_port({spawn, Params}, [stderr_to_stdout, exit_status]) to create an OS process, if the erlang process that created it dies, the os process stays alive.  I want the os process to die with the erlang process, often this is the case if the process reads stdin.

Currently this process does not read stdin and it does not die when the erlang process dies.

Any ideas how to do this?
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

Guilherme Andrade

On 25 Nov 2016 3:53 a.m., "Vans S" <[hidden email]> wrote:
>
> So far if I use open_port({spawn, Params}, [stderr_to_stdout, exit_status]) to create an OS process, if the erlang process that created it dies, the os process stays alive.  I want the os process to die with the erlang process, often this is the case if the process reads stdin.
>
> Currently this process does not read stdin and it does not die when the erlang process dies.
>
> Any ideas how to do this?

erlexec[1] might be what you're looking for.

[1]: https://github.com/saleyn/erlexec

> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

Raimo Niskanen-2
In reply to this post by Vans S
On Fri, Nov 25, 2016 at 03:53:32AM +0000, Vans S wrote:
> So far if I use open_port({spawn, Params}, [stderr_to_stdout, exit_status]) to create an OS process, if the erlang process that created it dies, the os process stays alive.  I want the os process to die with the erlang process, often this is the case if the process reads stdin.
>
> Currently this process does not read stdin and it does not die when the erlang process dies.
>
> Any ideas how to do this?

I have used a wrapper script that prints the process number on stdout and
then execs the target program.  Then I can kill the spawned process using
os:cmd or such.

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

José Valim-2
If I remember correctly, the stdin of the program started with open_port will be closed when the Erlang VM terminates. So if the OS process is listening to stdin and exiting when the stdin closes, you don't need to worry about terminating it.

When they don't do so, you can also write a script that spawns the OS process and traverses stdin until it closes and then it terminates the OS process when stdin closes. Something like:

#!/bin/bash
name=$1
shift
$name $*
pid=$!
while read line ; do
  :
done < /dev/stdin
kill -KILL $pid

If you save it as "wrap" then you can start your OS process as "wrap NAME ARGS". This can be handy if you cannot rely on C/C++ extensions. If anyone knows any drawback to such approach, I would love to hear.

José Valim
Skype: jv.ptec
Founder and Director of R&D


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

Per Hedeland
On 2016-11-25 11:27, José Valim wrote:
> If I remember correctly, the stdin of the program started with open_port will be closed when the Erlang VM terminates.

Right - this is guaranteed by the OS kernel, which closes all open file
descriptors for a process when it terminates. Should be true even for
Windows with whatever is used to communicate with port programs there.

> So if the OS process is listening to stdin and exiting when the stdin closes, you
> don't need to worry about terminating it.

Yes. And this is the *only* way to ensure that the port program *always*
terminates when it should - it covers all of

- port is explicitly closed
- port-owning Erlang process terminates
- Erlang VM terminates

With Raimo's suggestion, the port program will continue to run if the
Erlang VM terminates "abruptly" (e.g. killed by e.g. the OOM-killer, or
failing to allocate memory). The design that stipulates that port
programs should (attempt to) read stdin and terminate when they see EOF
wasn't done on a whim...

> When they don't do so, you can also write a script that spawns the OS process and traverses stdin until it closes and then it terminates the OS process when stdin closes. Something like:
>
>     #!/bin/bash
>     name=$1
>     shift
>     $name $*
>     pid=$!
>     while read line ; do
>       :
>     done < /dev/stdin
>     kill -KILL $pid
>
>
> If you save it as "wrap" then you can start your OS process as "wrap NAME ARGS". This can be handy if you cannot rely on C/C++ extensions. If anyone knows any drawback to such approach, I would love
> to hear.

Well, your script is missing a '&' on the "$name $*" line to make the
"target" program run in the (script's) background, but otherwise it
should be fine. I'd like to suggest a bit of simplification and
increased portability though:

   #!/bin/sh
   "$@" &
   pid=$!
   while read line ; do
     :
   done
   kill -KILL $pid

(And you could of course using something "nicer" than -KILL, e.g. -TERM,
if you are sure that it will be sufficient to terminate the program.)

--Per Hedeland
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

Vans S
Per Hedeland and José Valim that method works great.  One small peeve is it makes an extra process but the only way around this would be to patch the OS Processes code to terminate when stdin closes.  For now using the shell script is more then enough.



On Friday, November 25, 2016 6:33 AM, Per Hedeland <[hidden email]> wrote:
On 2016-11-25 11:27, José Valim wrote:
> If I remember correctly, the stdin of the program started with open_port will be closed when the Erlang VM terminates.

Right - this is guaranteed by the OS kernel, which closes all open file
descriptors for a process when it terminates. Should be true even for
Windows with whatever is used to communicate with port programs there.

> So if the OS process is listening to stdin and exiting when the stdin closes, you
> don't need to worry about terminating it.

Yes. And this is the *only* way to ensure that the port program *always*
terminates when it should - it covers all of

- port is explicitly closed
- port-owning Erlang process terminates
- Erlang VM terminates

With Raimo's suggestion, the port program will continue to run if the
Erlang VM terminates "abruptly" (e.g. killed by e.g. the OOM-killer, or
failing to allocate memory). The design that stipulates that port
programs should (attempt to) read stdin and terminate when they see EOF
wasn't done on a whim...

> When they don't do so, you can also write a script that spawns the OS process and traverses stdin until it closes and then it terminates the OS process when stdin closes. Something like:
>
>     #!/bin/bash
>     name=$1
>     shift
>     $name $*
>     pid=$!
>     while read line ; do
>       :
>     done < /dev/stdin
>     kill -KILL $pid
>
>
> If you save it as "wrap" then you can start your OS process as "wrap NAME ARGS". This can be handy if you cannot rely on C/C++ extensions. If anyone knows any drawback to such approach, I would love
> to hear.

Well, your script is missing a '&' on the "$name $*" line to make the
"target" program run in the (script's) background, but otherwise it
should be fine. I'd like to suggest a bit of simplification and
increased portability though:

   #!/bin/sh
   "$@" &
   pid=$!
   while read line ; do
     :
   done
   kill -KILL $pid

(And you could of course using something "nicer" than -KILL, e.g. -TERM,
if you are sure that it will be sufficient to terminate the program.)

--Per Hedeland

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

Per Hedeland
On 2016-11-25 18:17, Vans S wrote:
> Per Hedeland and José Valim that method works great.  One small peeve is it makes an extra process

Yes, but that shouldn't be any actual cost beyond a comparitively small
amount of memory (that can be mostly paged out even if you don't have
swap) - it doesn't actually *do* anything, just sits in a blocking
read(2) of its stdin.

> but the only way around this would be to patch the OS Processes code to terminate when stdin closes.

Assuming that you mean modifying the "target" program, yes - this would
be the "best" solution, but there are many cases where it is problematic
- obviously if you don't actually have the source code, but even if you
do, the modification can be non-trivial in a complex program, and it's a
pain to keep modifying the code and running the modified version when
new versions are released, etc.

> For now using the shell script is more then enough.

Great!

--Per
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

Vans S
> Yes, but that shouldn't be any actual cost beyond a comparitively small
> amount of memory (that can be mostly paged out even if you don't have
> swap) - it doesn't actually *do* anything, just sits in a blocking
> read(2) of its stdin.

The cost is indeed there, but in human cognitive resources :)

I need to manage these processes and know if something is running or not outside of erlang.  
A simple way I was doing this was by grepping /proc both for the process name and for
a uuid stored in its commandline. Maybe there is a better way?

With these 2 processes having duplicate command lines I need to write some extra logic.

Another key reason to grep /proc cmdline like this, is that I can guarantee a
process with a certain uuid is not started twice, say if an erlang process goes into an undefined state.




On Friday, November 25, 2016 2:38 PM, Per Hedeland <[hidden email]> wrote:
On 2016-11-25 18:17, Vans S wrote:
> Per Hedeland and José Valim that method works great.  One small peeve is it makes an extra process

Yes, but that shouldn't be any actual cost beyond a comparitively small
amount of memory (that can be mostly paged out even if you don't have
swap) - it doesn't actually *do* anything, just sits in a blocking
read(2) of its stdin.

> but the only way around this would be to patch the OS Processes code to terminate when stdin closes.

Assuming that you mean modifying the "target" program, yes - this would
be the "best" solution, but there are many cases where it is problematic
- obviously if you don't actually have the source code, but even if you
do, the modification can be non-trivial in a complex program, and it's a
pain to keep modifying the code and running the modified version when
new versions are released, etc.

> For now using the shell script is more then enough.

Great!


--Per
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How do you kill an OS process that was opened with open_port on a brutal_kill?

Michael Truog
In reply to this post by Vans S
On 11/25/2016 09:17 AM, Vans S wrote:
> Per Hedeland and José Valim that method works great.  One small peeve is it makes an extra process but the only way around this would be to patch the OS Processes code to terminate when stdin closes.  For now using the shell script is more then enough.
A well-behaved port should be checking the file descriptor to see if it is closed.  I prefer to use the poll function and check revents on the file descriptor for the POLLHUP, since I know that if that is present, Erlang has exited.  However, it is possible that the port execution takes a long time before actually getting to the poll function, so, it is nice to have a termination timeout on the Erlang side that uses os:cmd("kill -9 " ++ PID) to ensure the OS process actually dies at some point in time.  Otherwise, it is possible to suspend the port and have it hanging around forever.  If you use external services in CloudI, this is handled for you, which helps to avoid spending time on these details.

Best Regards,
Michael

> On Friday, November 25, 2016 6:33 AM, Per Hedeland <[hidden email]> wrote:
> On 2016-11-25 11:27, José Valim wrote:
>> If I remember correctly, the stdin of the program started with open_port will be closed when the Erlang VM terminates.
> Right - this is guaranteed by the OS kernel, which closes all open file
> descriptors for a process when it terminates. Should be true even for
> Windows with whatever is used to communicate with port programs there.
>
>> So if the OS process is listening to stdin and exiting when the stdin closes, you
>> don't need to worry about terminating it.
> Yes. And this is the *only* way to ensure that the port program *always*
> terminates when it should - it covers all of
>
> - port is explicitly closed
> - port-owning Erlang process terminates
> - Erlang VM terminates
>
> With Raimo's suggestion, the port program will continue to run if the
> Erlang VM terminates "abruptly" (e.g. killed by e.g. the OOM-killer, or
> failing to allocate memory). The design that stipulates that port
> programs should (attempt to) read stdin and terminate when they see EOF
> wasn't done on a whim...
>
>> When they don't do so, you can also write a script that spawns the OS process and traverses stdin until it closes and then it terminates the OS process when stdin closes. Something like:
>>
>>      #!/bin/bash
>>      name=$1
>>      shift
>>      $name $*
>>      pid=$!
>>      while read line ; do
>>        :
>>      done < /dev/stdin
>>      kill -KILL $pid
>>
>>
>> If you save it as "wrap" then you can start your OS process as "wrap NAME ARGS". This can be handy if you cannot rely on C/C++ extensions. If anyone knows any drawback to such approach, I would love
>> to hear.
> Well, your script is missing a '&' on the "$name $*" line to make the
> "target" program run in the (script's) background, but otherwise it
> should be fine. I'd like to suggest a bit of simplification and
> increased portability though:
>
>     #!/bin/sh
>     "$@" &
>     pid=$!
>     while read line ; do
>       :
>     done
>     kill -KILL $pid
>
> (And you could of course using something "nicer" than -KILL, e.g. -TERM,
> if you are sure that it will be sufficient to terminate the program.)
>
> --Per Hedeland
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions