aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src/socket.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded/src/socket.erl')
-rw-r--r--erts/preloaded/src/socket.erl22
1 files changed, 13 insertions, 9 deletions
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl
index 12b6c3ac55..5c1647290d 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -2111,6 +2111,16 @@ do_recvmsg(SockRef, BufSz, CtrlSz, EFlags, Timeout) ->
%%
%% close - close a file descriptor
%%
+%% Closing a socket is a two stage rocket (because of linger).
+%% We need to perform the actual socket close while in BLOCKING mode.
+%% But that would hang the entire VM, so what we do is divide the
+%% close in two steps:
+%% 1) nif_close + the socket_stop (nif) callback function
+%% This is for everything that can be done safely NON-BLOCKING.
+%% 2) nif_finalize_close which is executed by a *dirty* scheduler
+%% Before we call the socket close function, we se the socket
+%% BLOCKING. Thereby linger is handled properly.
+
-spec close(Socket) -> ok | {error, Reason} when
Socket :: socket(),
@@ -2124,16 +2134,10 @@ do_close(SockRef) ->
ok ->
nif_finalize_close(SockRef);
{ok, CloseRef} ->
- %% We must wait
+ %% We must wait for the socket_stop callback function to
+ %% complete its work
receive
- {'$socket', _, close, CloseRef} ->
-%% {close, CloseRef} ->
- %% <KOLLA>
- %%
- %% WHAT HAPPENS IF THIS PROCESS IS KILLED
- %% BEFORE WE CAN EXECUTE THE FINAL CLOSE???
- %%
- %% </KOLLA>
+ {'$socket', SockRef, close, CloseRef} ->
nif_finalize_close(SockRef)
end;
{error, _} = ERROR ->