diff options
author | Raimo Niskanen <raimo@erlang.org> | 2020-01-09 17:01:59 +0100 |
---|---|---|
committer | Raimo Niskanen <raimo@erlang.org> | 2020-01-23 17:26:26 +0100 |
commit | ac4c222f96c4d24b7939be7209d8aed0abf1eb83 (patch) | |
tree | 24335eeba1d3838e08008d24a23ec55a7d79f13a /erts | |
parent | 8a577a4682f8b050f3d0dc0433b331db5bf57b4d (diff) | |
download | erlang-ac4c222f96c4d24b7939be7209d8aed0abf1eb83.tar.gz |
Fix close and abort handling
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 75 | ||||
-rw-r--r-- | erts/emulator/test/socket_SUITE.erl | 4 | ||||
-rw-r--r-- | erts/preloaded/ebin/socket.beam | bin | 79808 -> 80272 bytes | |||
-rw-r--r-- | erts/preloaded/src/socket.erl | 35 |
4 files changed, 73 insertions, 41 deletions
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 688bac5751..3482c1e950 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -6732,12 +6732,14 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env, if ((argc != 4) || !GET_BIN(env, argv[2], &sndData) || !GET_UINT(env, argv[3], &eflags)) { + SSDBG( descP, ("SOCKET", "nif_send -> argv decode failed\r\n") ); return enif_make_badarg(env); } sockRef = argv[0]; // We need this in case we send in case we send abort sendRef = argv[1]; if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { + SSDBG( descP, ("SOCKET", "nif_send -> get resource failed\r\n") ); return enif_make_badarg(env); } @@ -6749,8 +6751,10 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env, "\r\n eFlags: 0x%lX" "\r\n", descP->sock, sockRef, sendRef, sndData.size, eflags) ); - if (!esendflags2sendflags(eflags, &flags)) + if (!esendflags2sendflags(eflags, &flags)) { + SSDBG( descP, ("SOCKET", "nif_send -> sendflags decode failed\r\n") ); return esock_make_error(env, esock_atom_einval); + } SSDBG( descP, ("SOCKET", "nif_send -> flags: 0x%lX\r\n", flags) ); @@ -6795,12 +6799,17 @@ ERL_NIF_TERM esock_send(ErlNifEnv* env, ssize_t written; ERL_NIF_TERM writerCheck; - if (!descP->isWritable) - return enif_make_badarg(env); + if (!descP->isWritable) { + SSDBG( descP, ("SOCKET", "esock_send -> return not writable\r\n") ); + return esock_make_error(env, atom_closed); + } /* Ensure that we either have no current writer or we are it */ - if (!send_check_writer(env, descP, sendRef, &writerCheck)) + if (!send_check_writer(env, descP, sendRef, &writerCheck)) { + SSDBG( descP, ("SOCKET", "esock_send -> writer check failed: " + "\r\n %T\r\n", writerCheck) ); return writerCheck; + } /* We ignore the wrap for the moment. * Maybe we should issue a wrap-message to controlling process... @@ -6862,6 +6871,7 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env, if ((argc != 5) || !GET_BIN(env, argv[2], &sndData) || !GET_UINT(env, argv[4], &eflags)) { + SSDBG( descP, ("SOCKET", "nif_sendto -> argv decode failed\r\n") ); return enif_make_badarg(env); } sockRef = argv[0]; // We need this in case we send abort (to the caller) @@ -6869,6 +6879,7 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env, eSockAddr = argv[3]; if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { + SSDBG( descP, ("SOCKET", "nif_sendto -> get resource failed\r\n") ); return enif_make_badarg(env); } @@ -6927,12 +6938,17 @@ ERL_NIF_TERM esock_sendto(ErlNifEnv* env, ssize_t written; ERL_NIF_TERM writerCheck; - if (!descP->isWritable) - return enif_make_badarg(env); + if (!descP->isWritable) { + SSDBG( descP, ("SOCKET", "esock_sendto -> return not writable\r\n") ); + return esock_make_error(env, atom_closed); + } /* Ensure that we either have no current writer or we are it */ - if (!send_check_writer(env, descP, sendRef, &writerCheck)) + if (!send_check_writer(env, descP, sendRef, &writerCheck)) { + SSDBG( descP, ("SOCKET", "esock_sendto -> writer check failed: " + "\r\n %T\r\n", writerCheck) ); return writerCheck; + } /* We ignore the wrap for the moment. * Maybe we should issue a wrap-message to controlling process... @@ -6993,6 +7009,7 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, if ((argc != 4) || !IS_MAP(env, argv[2]) || !GET_UINT(env, argv[3], &eflags)) { + SSDBG( descP, ("SOCKET", "nif_sendmsg -> argv decode failed\r\n") ); return enif_make_badarg(env); } sockRef = argv[0]; // We need this in case we send abort (to the caller) @@ -7000,6 +7017,7 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, eMsgHdr = argv[2]; if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { + SSDBG( descP, ("SOCKET", "nif_sendmsg -> get resource failed\r\n") ); return enif_make_badarg(env); } @@ -7011,8 +7029,10 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, "\r\n", descP->sock, argv[0], sendRef, eflags) ); - if (!esendflags2sendflags(eflags, &flags)) + if (!esendflags2sendflags(eflags, &flags)) { + SSDBG( descP, ("SOCKET", "nif_sendmsg -> sendflags decode failed\r\n") ); return esock_make_error(env, esock_atom_einval); + } MLOCK(descP->writeMtx); @@ -7054,19 +7074,15 @@ ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env, char* xres; if (!descP->isWritable) { - SSDBG( descP, ("SOCKET", "esock_sendmsg -> not writable\r\n") ); - - return enif_make_badarg(env); + return esock_make_error(env, atom_closed); } /* Ensure that we either have no current writer or we are it */ if (!send_check_writer(env, descP, sendRef, &writerCheck)) { - - SSDBG( descP, - ("SOCKET", "esock_sendmsg -> writer check failed: " - "\r\n %T\r\n", writerCheck) ); - + SSDBG( descP, + ("SOCKET", "esock_sendmsg -> writer check failed: " + "\r\n %T\r\n", writerCheck) ); return writerCheck; } @@ -7374,7 +7390,7 @@ ERL_NIF_TERM esock_recv(ErlNifEnv* env, flags) ); if (!descP->isReadable) - return enif_make_badarg(env); + return esock_make_error(env, atom_closed); /* Check if there is already a current reader and if its us */ if (!recv_check_reader(env, descP, recvRef, &readerCheck)) @@ -7539,7 +7555,7 @@ ERL_NIF_TERM esock_recvfrom(ErlNifEnv* env, "\r\n", len, bufSz, flags) ); if (!descP->isReadable) - return enif_make_badarg(env); + return esock_make_error(env, atom_closed); /* Check if there is already a current reader and if its us */ if (!recv_check_reader(env, descP, recvRef, &readerCheck)) @@ -7714,7 +7730,7 @@ ERL_NIF_TERM esock_recvmsg(ErlNifEnv* env, "\r\n", bufSz, bufLen, ctrlSz, ctrlLen, flags) ); if (!descP->isReadable) - return enif_make_badarg(env); + return esock_make_error(env, atom_closed); /* Check if there is already a current reader and if its us */ if (!recv_check_reader(env, descP, recvRef, &readerCheck)) @@ -15414,6 +15430,8 @@ BOOLEAN_T send_check_writer(ErlNifEnv* env, if (enif_self(env, &caller) == NULL) { *checkResult = esock_make_error(env, atom_exself); + SSDBG( descP, ("SOCKET", + "send_check_writer -> exself\r\n") ); return FALSE; } @@ -15427,7 +15445,7 @@ BOOLEAN_T send_check_writer(ErlNifEnv* env, if (!writer_search4pid(env, descP, &caller)) *checkResult = writer_push(env, descP, caller, ref); else - *checkResult = esock_make_error(env, esock_atom_eagain); + *checkResult = esock_make_error(env, atom_exbusy); SSDBG( descP, ("SOCKET", @@ -15944,8 +15962,8 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env, */ if ((read == 0) && (descP->type == SOCK_STREAM)) { - - res = esock_make_error(env, atom_closed); + ERL_NIF_TERM reason = atom_closed; + res = esock_make_error(env, reason); ESOCK_CNT_INC(env, descP, sockRef, atom_read_fails, &descP->readFails, 1); @@ -15958,7 +15976,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env, * We must also notify any waiting readers! */ - recv_error_current_reader(env, descP, sockRef, res); + recv_error_current_reader(env, descP, sockRef, reason); FREE_BIN(bufP); @@ -16247,7 +16265,8 @@ ERL_NIF_TERM recv_check_fail_econnreset(ErlNifEnv* env, ERL_NIF_TERM sockRef, ERL_NIF_TERM recvRef) { - ERL_NIF_TERM reason = esock_make_error(env, atom_econnreset); + ERL_NIF_TERM reason = atom_econnreset; + ERL_NIF_TERM res = esock_make_error(env, atom_econnreset); /* <KOLLA> * @@ -16288,7 +16307,7 @@ ERL_NIF_TERM recv_check_fail_econnreset(ErlNifEnv* env, } MUNLOCK(descP->writeMtx); - return reason; + return res; } @@ -16339,11 +16358,11 @@ ERL_NIF_TERM recv_check_fail_gen(ErlNifEnv* env, int saveErrno, ERL_NIF_TERM sockRef) { - ERL_NIF_TERM res = esock_make_error_errno(env, saveErrno); + ERL_NIF_TERM reason = MKA(env, erl_errno_id(saveErrno)); - recv_error_current_reader(env, descP, sockRef, res); + recv_error_current_reader(env, descP, sockRef, reason); - return res; + return esock_make_error(env, reason); } diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 4736e182de..bce4ae1a5f 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -15856,7 +15856,7 @@ api_opt_sock_timestamp_tcp(InitState) -> ok end}, #{desc => "await recv reply 2 (from server, w timestamp)", - cmd => fun(#{sock := Sock, recv := Recv}) -> + cmd => fun(#{sock := Sock, recv := Recv, get := Get}) -> case Recv(Sock) of {ok, {[#{level := socket, type := timestamp, @@ -15866,6 +15866,8 @@ api_opt_sock_timestamp_tcp(InitState) -> "~n ~p", [TS]), ok; {ok, {BadCMsgHdrs, ?BASIC_REP}} -> + ?SEV_EPRINT("Current timestamp value:" + " ~p", [Get(Sock)]), {error, {unexpected_reply_cmsghdrs, BadCMsgHdrs}}; {ok, {[#{level := socket, diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex bd238f0f7d..29b4c20ece 100644 --- a/erts/preloaded/ebin/socket.beam +++ b/erts/preloaded/ebin/socket.beam diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index dc6085eb52..50e1f82cb2 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -1679,10 +1679,10 @@ send_common(SockRef, Data, To, EFlags, Deadline, SendName) -> SockRef, Data, To, EFlags, Deadline, SendName); {?ESOCK_TAG, _Socket, abort, {SendRef, Reason}} -> - {error, Reason} + {error, {Reason, size(Data)}} after Timeout -> - cancel(SockRef, SendName, SendRef), + _ = cancel(SockRef, SendName, SendRef), {error, {timeout, size(Data)}} end; @@ -1707,10 +1707,10 @@ send_common(SockRef, Data, To, EFlags, Deadline, SendName) -> SockRef, Data, To, EFlags, Deadline, SendName); {?ESOCK_TAG, _Socket, abort, {SendRef, Reason}} -> - {error, Reason} + {error, {Reason, size(Data)}} after Timeout -> - cancel(SockRef, SendName, SendRef), + _ = cancel(SockRef, SendName, SendRef), {error, {timeout, size(Data)}} end; @@ -1720,8 +1720,6 @@ send_common(SockRef, Data, To, EFlags, Deadline, SendName) -> end. - - %% --------------------------------------------------------------------------- %% @@ -1901,7 +1899,7 @@ do_sendmsg(SockRef, MsgHdr, EFlags, Deadline) -> %% %% We need to cancel this partial write. %% - cancel(SockRef, sendmsg, SendRef), + _ = cancel(SockRef, sendmsg, SendRef), {ok, do_sendmsg_rest(maps:get(iov, MsgHdr), Written)}; @@ -1921,10 +1919,13 @@ do_sendmsg(SockRef, MsgHdr, EFlags, Deadline) -> Timeout = timeout(Deadline), receive {?ESOCK_TAG, #socket{ref = SockRef}, select, SendRef} -> - do_sendmsg(SockRef, MsgHdr, EFlags, Deadline) + do_sendmsg(SockRef, MsgHdr, EFlags, Deadline); + + {?ESOCK_TAG, _Socket, abort, {SendRef, Reason}} -> + {error, Reason} after Timeout -> - cancel(SockRef, sendmsg, SendRef), + _ = cancel(SockRef, sendmsg, SendRef), {error, timeout} end; @@ -3909,19 +3910,29 @@ cancel(SockRef, Op, OpRef) -> case nif_cancel(SockRef, Op, OpRef) of %% The select has already completed {error, select_sent} -> - flush_select_msgs(SockRef, OpRef); + flush_select_msg(SockRef, OpRef), + _ = flush_abort_msg(SockRef, OpRef), + ok; Other -> + _ = flush_abort_msg(SockRef, OpRef), Other end. -flush_select_msgs(SockRef, Ref) -> +flush_select_msg(SockRef, Ref) -> receive {?ESOCK_TAG, #socket{ref = SockRef}, select, Ref} -> - flush_select_msgs(SockRef, Ref) + ok after 0 -> ok end. +flush_abort_msg(SockRef, Ref) -> + receive + {?ESOCK_TAG, #socket{ref = SockRef}, abort, {Ref, Reason}} -> + Reason + after 0 -> + ok + end. %% formated_timestamp() -> %% format_timestamp(os:timestamp()). |