[erlang-questions] spawn problem
ok
ok@REDACTED
Tue Mar 27 04:17:05 CEST 2007
On 27 Mar 2007, at 1:17 pm, Fernando Ipar <fipar@REDACTED>
wrote
> test(_, 0) ->
> true;
> test(Command, Threads) when number(Threads) ->
> spawn('os', 'cmd', [Command]),
> test(Command, Threads - 1).
You do not need quotation marks around atoms like os and cmd.
>
> start() ->
> Command = list_to_atom(os:getenv("Command")),
> Threads = list_to_integer(os:getenv("Threads")),
> test(Command,Threads).
You do not need to convert Command to an atom; the documentation for
os: says
cmd(Command) -> string()
Types:
Command = string() | atom()
Mind you, sending an atom in a message to a process is cheaper than
sending a string,
but since atoms are not garbage collected, there's an advantage to
using strings in a
long-running process.
> My problem is that if I call this with more than 508 'Threads' (bear
> with me on the variable name selection..) I get ... emfile
...
> open files (-n) 1024
508 is suspiciously close to 512, which is half of 1024.
Doesn't it look to you as though os:cmd/1 is opening TWO files?
Looking in lib/kernel/src/os.erl,
cmd/1 -> unix_cmd/1 -> spawns unix_cmd/1 -> creates a port using
start_port/0
-> open_port({spawn,"sh -s unix:cmd 2>&1"}, [stream])
The command is then sent to the STANDARD INPUT of that new process
and the STANDARD OUTPUT of the process read and returned to the
original caller.
It would be a little clearer if the documentation for
erlang:open_port/2 said explicitly
that open_port({spawn,...},[...]) used up two file descriptors, but
this text:
use_stdio
This is only valid for {spawn, Command}.
It allows the standard input and output (file descriptors 0 and 1)
of the spawned (UNIX) process for communication with Erlang.
does give you a strong hint.
Why does os:cmd/1 send the command to the shell's standard input,
sh -s unix:cmd <"your command string" ,
rather than
sh -c "your command string" </dev/null ?
Not being the author, I can't say for sure, but there is an upper
bound on the size of a
command in the second case which does not apply in the first (if the
Command is passed as
a string, because atoms have their own limits).
> While this project in particular is not important, I'll appreciate any
> help with this problem, since I'd like to know how many processes I
> can
> create in erlang, and what tweaking needs to be
> done to the OS (if any).
Well, now you know the answer. If sysconf(_SC_OPEN_MAX) is N, the
answer is
"a little bit less than N/2", and apparently it's (N-8)/2.
You can create any number of processes; the limit is on the number
that can be
active at the same time. The limit is determined by sysconf
(_SC_CHILD_MAX) --
25813 on my machine -- and sysconf(_SC_OPEN_MAX)/2 minus a bit -- my
machine
limits the number of open files to 256, so I can only have a little
over 100
os:cmd/1 processes active at the same time.
Since there is no guaranteed way for an Erlang program to determine
whether there
will be enough file descriptors left or not, a reasonable extension
might be to
add a {timeout,T} option to to erlang:open_port/2 to wait up to T
milliseconds for
sufficient file descriptors to become available again. Until
something like that
is done, the simplest thing is to keep the number of OS processes you
create low,
and the next simplest is to write your own wrapper which catches
emfile, waits for
some time, and retries, giving up after some number of retries.
More information about the erlang-questions
mailing list