summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
authorRaimo Niskanen <raimo@erlang.org>2020-01-09 17:01:59 +0100
committerRaimo Niskanen <raimo@erlang.org>2020-01-23 17:26:26 +0100
commitac4c222f96c4d24b7939be7209d8aed0abf1eb83 (patch)
tree24335eeba1d3838e08008d24a23ec55a7d79f13a /erts
parent8a577a4682f8b050f3d0dc0433b331db5bf57b4d (diff)
downloaderlang-ac4c222f96c4d24b7939be7209d8aed0abf1eb83.tar.gz
Fix close and abort handling
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/nifs/common/socket_nif.c75
-rw-r--r--erts/emulator/test/socket_SUITE.erl4
-rw-r--r--erts/preloaded/ebin/socket.beambin79808 -> 80272 bytes
-rw-r--r--erts/preloaded/src/socket.erl35
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
index bd238f0f7d..29b4c20ece 100644
--- a/erts/preloaded/ebin/socket.beam
+++ b/erts/preloaded/ebin/socket.beam
Binary files differ
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()).