aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src/os.erl
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2017-02-22 15:39:42 +0100
committerLukas Larsson <[email protected]>2017-02-22 15:39:42 +0100
commit1ae931102f106c2e12d110cd674e1c3dd988bfd2 (patch)
treee3f78c7f3a782208afea3d9d09a8d90e392b1e1a /lib/kernel/src/os.erl
parent84c821dc97fae0d035b3158fb7a3f97320ad413b (diff)
parent833de830b9805666f3a6a3752d5339aa0a577a3e (diff)
downloadotp-1ae931102f106c2e12d110cd674e1c3dd988bfd2.tar.gz
otp-1ae931102f106c2e12d110cd674e1c3dd988bfd2.tar.bz2
otp-1ae931102f106c2e12d110cd674e1c3dd988bfd2.zip
Merge branch 'maint'
Diffstat (limited to 'lib/kernel/src/os.erl')
-rw-r--r--lib/kernel/src/os.erl24
1 files changed, 15 insertions, 9 deletions
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index c3ffcb3f70..7e83b17add 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -298,12 +298,11 @@ get_data(Port, MonRef, Eot, Sofar) ->
more ->
get_data(Port, MonRef, Eot, [Sofar,Bytes]);
Last ->
- Port ! {self(), close},
- flush_until_closed(Port),
- flush_exit(Port),
+ catch port_close(Port),
+ flush_until_down(Port, MonRef),
iolist_to_binary([Sofar, Last])
end;
- {'DOWN', MonRef, _, _ , _} ->
+ {'DOWN', MonRef, _, _, _} ->
flush_exit(Port),
iolist_to_binary(Sofar)
end.
@@ -317,18 +316,25 @@ eot(Bs, Eot) ->
binary:part(Bs,{0, Pos})
end.
-flush_until_closed(Port) ->
+%% When port_close returns we know that all the
+%% messages sent have been sent and that the
+%% DOWN message is after them all.
+flush_until_down(Port, MonRef) ->
receive
{Port, {data, _Bytes}} ->
- flush_until_closed(Port);
- {Port, closed} ->
- true
+ flush_until_down(Port, MonRef);
+ {'DOWN', MonRef, _, _, _} ->
+ flush_exit(Port)
end.
+%% The exit signal is always delivered before
+%% the down signal, so we can be sure that if there
+%% was an exit message sent, it will be in the
+%% mailbox now.
flush_exit(Port) ->
receive
{'EXIT', Port, _} ->
ok
- after 1 -> % force context switch
+ after 0 ->
ok
end.