aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorRaimo Niskanen <[email protected]>2013-06-15 13:57:46 +0200
committerRaimo Niskanen <[email protected]>2013-06-15 13:57:46 +0200
commitc7fed1781bec1fbc893931a4d732a38a55f9ceea (patch)
treece8c8f339d9ee29175345e59e750aa28f6582378 /erts
parentbda0f0b1a0b990b095fc46c3a5c7085f69f08480 (diff)
parent17035a025c7b6fbcdd05f0385ba42546608b4c53 (diff)
downloadotp-c7fed1781bec1fbc893931a4d732a38a55f9ceea.tar.gz
otp-c7fed1781bec1fbc893931a4d732a38a55f9ceea.tar.bz2
otp-c7fed1781bec1fbc893931a4d732a38a55f9ceea.zip
Merge branch 'raimo/race-in-prim_inet-close/OTP-10497' into maint
* raimo/race-in-prim_inet-close/OTP-10497: Improve solution
Diffstat (limited to 'erts')
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin70112 -> 70520 bytes
-rw-r--r--erts/preloaded/src/prim_inet.erl28
2 files changed, 26 insertions, 2 deletions
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index ef305ae1e9..8638ef677e 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 36a650cb5c..fb1269cf91 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -177,8 +177,32 @@ close_pend_loop(S, N) ->
end.
close_port(S) ->
- catch erlang:port_close(S),
- receive {'EXIT',S,_} -> ok after 0 -> ok end.
+ case erlang:process_info(self(), trap_exit) of
+ {trap_exit,true} ->
+ %% Ensure exit message and consume it
+ link(S),
+ %% This is still not a perfect solution.
+ %%
+ %% The problem is to close the port and consume any exit
+ %% message while not knowing if this process traps exit
+ %% nor if this process has a link to the port. Here we
+ %% just knows that this process traps exit.
+ %%
+ %% If we right here get killed for some reason that exit
+ %% signal will propagate to the port and onwards to anyone
+ %% that is linked to the port. E.g when we close a socket
+ %% that is not ours.
+ %%
+ %% The problem can be solved with lists:member on our link
+ %% list but we deem that as potentially too expensive. We
+ %% need an is_linked/1 function or guard, or we need
+ %% a port_close function that can atomically unlink...
+ catch erlang:port_close(S),
+ receive {'EXIT',S,_} -> ok end;
+ {trap_exit,false} ->
+ catch erlang:port_close(S),
+ ok
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%