From 4ff181e69fc129576333c04a9d1d0c97b6770347 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 21 Feb 2019 14:57:59 +0100 Subject: [socket] More fixes to socket close Better handling of socket close. The 'closeRef' needed its own environment to make if work in both cases (both called and scheduled). Also Introduced the enif select wrapper functions (read, write, stop and cancel). Also add error handling at every time one of these functions are called. OTP-14831 --- erts/preloaded/ebin/socket.beam | Bin 70288 -> 70312 bytes erts/preloaded/src/socket.erl | 22 +++++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'erts/preloaded') diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index 93b5fc215b..e44dff8475 100644 Binary files a/erts/preloaded/ebin/socket.beam and b/erts/preloaded/ebin/socket.beam differ 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} -> - %% - %% - %% WHAT HAPPENS IF THIS PROCESS IS KILLED - %% BEFORE WE CAN EXECUTE THE FINAL CLOSE??? - %% - %% + {'$socket', SockRef, close, CloseRef} -> nif_finalize_close(SockRef) end; {error, _} = ERROR -> -- cgit v1.2.3