diff options
Diffstat (limited to 'lib/kernel/src/os.erl')
-rw-r--r-- | lib/kernel/src/os.erl | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 81b70a7fee..f8519d3a5e 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -254,7 +254,19 @@ mk_cmd(_,Cmd) -> {"/bin/sh -s unix:cmd", [out], %% We insert a new line after the command, in case the command %% contains a comment character. - ["(", unicode:characters_to_binary(Cmd), "\n); echo \"\^D\"\n"], + %% + %% The </dev/null closes stdin, which means that programs + %% that use a closed stdin as an termination indicator works. + %% An example of such a program is 'more'. + %% + %% The "echo ^D" is used to indicate that the program has executed + %% and we should return any output we have gotten. We cannot use + %% termination of the child or closing of stdin/stdout as then + %% starting background jobs from os:cmd will block os:cmd. + %% + %% I tried changing this to be "better", but got bombarded with + %% backwards incompatibility bug reports, so leave this as it is. + ["(", unicode:characters_to_binary(Cmd), "\n) </dev/null; echo \"\^D\"\n"], <<$\^D>>}. validate(Atom) when is_atom(Atom) -> @@ -279,15 +291,11 @@ get_data(Port, MonRef, Eot, Sofar) -> Last -> Port ! {self(), close}, flush_until_closed(Port), + flush_exit(Port), iolist_to_binary([Sofar, Last]) end; {'DOWN', MonRef, _, _ , _} -> - receive - {'EXIT', Port, _} -> - ok - after 1 -> % force context switch - ok - end, + flush_exit(Port), iolist_to_binary(Sofar) end. @@ -307,3 +315,11 @@ flush_until_closed(Port) -> {Port, closed} -> true end. + +flush_exit(Port) -> + receive + {'EXIT', Port, _} -> + ok + after 1 -> % force context switch + ok + end. |