It is the responsibility of the port program to shut down when stdin reaches EOF.
This behaviour/expectation confused me too at some point, but it probably has its merits: not all software is designed for "let it crash", so simply killing the port program might be too crude in some circumstances.
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
It is the responsibility of the port program to shut down when stdin reaches EOF.
This behaviour/expectation confused me too at some point, but it probably has its merits: not all software is designed for "let it crash", so simply killing the port program might be too crude in some circumstances.
I remember this was something I had going. Let me dig code:
----
#!/bin/sh
(cat && kill 0) | opentracker $*
----
So the trick is that the … && kill 0 part sends a kill signal to all processes in the current process group. This lets you stop another process since cat(1) understands what happens when stdin is closed and handles it accordingly.
I've only used it in tests though so it may need work for real programs
Hi Erik,Well that's fine, but it should be documented a bit more clearly IMHO.On 27 Sep 2012, at 03:20, Erik Søe Sørensen wrote:It is the responsibility of the port program to shut down when stdin reaches EOF.
This behaviour/expectation confused me too at some point, but it probably has its merits: not all software is designed for "let it crash", so simply killing the port program might be too crude in some circumstances.
The external program resides in another OS process. By default, it should read from standard input (file descriptor 0) and write to standard output (file descriptor 1). The external program should terminate when the port is closed.
Also the port program, in this instance, is another beam emulator, so it's clearly *not* going to behave that way!
Currently the connected process for the port has 3 shutdown modes:1. rpc:call(Node, custom_app, stop, [])2. close_port(Port)3. open_port({spawn, "kill -9 " ++ OsPid, Opts)
Item 3 is the least preferable as it is not portable (relies on 'kill' being a shell built-in, etc) and requires that the os process id is known. It sounds like (2) is not a workable solution unless the external program is hand written to deal with 'stdin reaches EOF'. This is less than ideal, as it means that open_port/2 is not much use for spawning (and monitoring thereafter) arbitrary programs unless you're willing to live with the fact that you're not able to shut them down by closing the port.
2012/9/27 Jesper Louis Andersen <jesper.lou...@erlang-solutions.com>I remember this was something I had going. Let me dig code:
----
#!/bin/sh
(cat && kill 0) | opentracker $*Nice incantation. I was just about to suggest using a wrapper program, but I probably wouldn't have thought of that variation.
----
So the trick is that the … && kill 0 part sends a kill signal to all processes in the current process group. This lets you stop another process since cat(1) understands what happens when stdin is closed and handles it accordingly.
I've only used it in tests though so it may need work for real programsSuch as replacing "&&" with ";" ? :-)
Just in case someone came along and killed the cat. (Can't at the moment imagine other scenarios where cat would exit with non-zero return values, but they probably exist.)
Also, replace $* with "$@" (including the quotes), for proper handling of parameters with spaces in them and such.
2012/9/27 Tim Watson <watson....@gmail.com>Hi Erik,Well that's fine, but it should be documented a bit more clearly IMHO.On 27 Sep 2012, at 03:20, Erik Søe Sørensen wrote:It is the responsibility of the port program to shut down when stdin reaches EOF.
This behaviour/expectation confused me too at some point, but it probably has its merits: not all software is designed for "let it crash", so simply killing the port program might be too crude in some circumstances.It's not in the API docs for open_port(), but in the section in the manual which definesports (http://www.erlang.org/doc/reference_manual/ports.html#id84207) it does sayThe external program resides in another OS process. By default, it should read from standard input (file descriptor 0) and write to standard output (file descriptor 1). The external program should terminate when the port is closed.
Also the port program, in this instance, is another beam emulator, so it's clearly *not* going to behave that way!Why not? - see below.
You could add
4. Ensure that the node runs a reading loop which detects EOF - e.g. using file:read_line(standard_io) or file:read(standard_io, SomeBlockSize).
Example for detecting EOF:
erl -noshell -eval 'F=fun(G)->X=file:read_line(standard_io), io:format("~p\n", [X]), X==eof orelse G(G) end, F(F), init:stop().'
You can even do exactly this in practise: put the loop code on the command line.
Item 3 is the least preferable as it is not portable (relies on 'kill' being a shell built-in, etc) and requires that the os process id is known. It sounds like (2) is not a workable solution unless the external program is hand written to deal with 'stdin reaches EOF'. This is less than ideal, as it means that open_port/2 is not much use for spawning (and monitoring thereafter) arbitrary programs unless you're willing to live with the fact that you're not able to shut them down by closing the port.
No, the port mechanism was apparently not meant for arbitrary slave programs. However, a little wrapping can often get you far, as Jesper demonstrated earlier.
2012/9/27 Jesper Louis Andersen <jesper.lou...@erlang-solutions.com>I remember this was something I had going. Let me dig code:
----
#!/bin/sh
(cat && kill 0) | opentracker $*Nice incantation. I was just about to suggest using a wrapper program, but I probably wouldn't have thought of that variation.
----
So the trick is that the … && kill 0 part sends a kill signal to all processes in the current process group. This lets you stop another process since cat(1) understands what happens when stdin is closed and handles it accordingly.
I've only used it in tests though so it may need work for real programsSuch as replacing "&&" with ";" ? :-)
Just in case someone came along and killed the cat. (Can't at the moment imagine other scenarios where cat would exit with non-zero return values, but they probably exist.)
Also, replace $* with "$@" (including the quotes), for proper handling of parameters with spaces in them and such.
I have the following on linux and everything builds fine:
$ autoconf -V
autoconf (GNU Autoconf) 2.68
$ libtool --version
libtool (GNU libtool) 2.4
$ ./build
$ make
$ make install
$ tree install
install
└── exec-1.0
├── ebin
│ ├── exec.app
│ ├── exec_app.beam
│ └── exec.beam
├── include
│ └── exec.hrl
├── priv
│ └── x86_64-unknown-linux-gnu
│ └── bin
│ └── exec-port
└── src
├── exec_app.erl
└── exec.erl
On 9/28/2012 7:45 AM, Tim Watson wrote:> The project doesn't appear to
$ grep "^macro_version" /usr/bin/libtool
macro_version=2.4
and if yours is different, try to upgrade it.
In order to simplify the build process I'll try to convert erlexec to
use rebar some time next week, which will eliminate autotools-based
toolchain. Need to figure out with rebar how to test and optionally
enable conditional defines based on presence of special C headers such
as "sys/capability.h" when compiling a port program.
On 9/28/2012 5:16 PM, Tim Watson wrote:> Well I do, but clearly not the
where $ARCH is the result of the call:
erlang:system_info(system_architecture)
I was thinking of setting ARCH in the pre-compile hook. However, it
doesn't seem that the "port_specs" config clause allows expansion of
environment variables, so if the "ARCH" variable has a value, the
following won't work:
{port_specs, [{"priv/$ARCH/exec-port", ["c_src/*.cpp"]}]}.
Is there a work-around I could use to accomplish this?
-module(example).
post_compile(Conf, _) ->
%% move the binar wherever you want
ok.
Below please find a version of erlexec that uses rebar:
https://github.com/saleyn/erlexec
Along with its documentation:
http://saleyn.github.com/erlexec
The old repository http://code.google.com/p/erlexec/ is deprecated.
Please let me know if this builds on other OS's besides Linux.
Regards,
Serge
On 9/29/2012 5:23 AM, Tim Watson wrote: