From 8a820377bb3e2e506cdff6011057d78507544142 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 21 Jan 2019 14:46:07 +0100 Subject: [socket-nif] Add support for otp option fd Add a way to *get* the file descriptor (fd) of a socket. Useful mostly for debugging. OTP-15528 --- erts/doc/src/socket_usage.xml | 9 ++++++- erts/emulator/nifs/common/socket_nif.c | 35 ++++++++++++++++++------ erts/emulator/test/socket_SUITE.erl | 48 +++++++++------------------------ erts/preloaded/ebin/socket.beam | Bin 70272 -> 70344 bytes erts/preloaded/src/socket.erl | 25 ++++++----------- 5 files changed, 55 insertions(+), 62 deletions(-) diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index 1ea29097c3..401a70992f 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -4,7 +4,7 @@
- 20182018 + 20182019 Ericsson AB. All Rights Reserved. @@ -102,6 +102,13 @@ yes default only valid for set + + fd + integer() + no + yes + none +

Options for level socket:

diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 6dcd4ae623..44aa44f5fc 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2018-2018. All Rights Reserved. + * Copyright Ericsson AB 2018-2019. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -519,6 +519,7 @@ typedef union { #define SOCKET_OPT_OTP_RCVBUF 4 #define SOCKET_OPT_OTP_RCVCTRLBUF 6 #define SOCKET_OPT_OTP_SNDCTRLBUF 7 +#define SOCKET_OPT_OTP_FD 8 #define SOCKET_OPT_OTP_DOMAIN 0xFF01 // INTERNAL AND ONLY GET #define SOCKET_OPT_OTP_TYPE 0xFF02 // INTERNAL AND ONLY GET #define SOCKET_OPT_OTP_PROTOCOL 0xFF03 // INTERNAL AND ONLY GET @@ -1561,6 +1562,8 @@ static ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, SocketDescriptor* descP); static ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, SocketDescriptor* descP); +static ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env, + SocketDescriptor* descP); static ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env, SocketDescriptor* descP); static ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env, @@ -10031,6 +10034,10 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, result = ngetopt_otp_sndctrlbuf(env, descP); break; + case SOCKET_OPT_OTP_FD: + result = ngetopt_otp_fd(env, descP); + break; + /* *** INTERNAL *** */ case SOCKET_OPT_OTP_DOMAIN: result = ngetopt_otp_domain(env, descP); @@ -10058,7 +10065,7 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, } -/* ngetopt_otp_debug - Handle the OTP (level) debug options +/* ngetopt_otp_debug - Handle the OTP (level) debug option */ static ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env, @@ -10070,7 +10077,7 @@ ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env, } -/* ngetopt_otp_iow - Handle the OTP (level) iow options +/* ngetopt_otp_iow - Handle the OTP (level) iow option */ static ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env, @@ -10082,7 +10089,7 @@ ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env, } -/* ngetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process options +/* ngetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process option */ static ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env, @@ -10095,7 +10102,7 @@ ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env, -/* ngetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf options +/* ngetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option */ static ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env, @@ -10107,7 +10114,7 @@ ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env, } -/* ngetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf options +/* ngetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option */ static ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, @@ -10119,7 +10126,7 @@ ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, } -/* ngetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf options +/* ngetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option */ static ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, @@ -10131,7 +10138,19 @@ ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, } -/* ngetopt_otp_domain - Handle the OTP (level) domain options. +/* ngetopt_otp_fd - Handle the OTP (level) fd option + */ +static +ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env, + SocketDescriptor* descP) +{ + ERL_NIF_TERM eVal = MKI(env, descP->sock); + + return esock_make_ok2(env, eVal); +} + + +/* ngetopt_otp_domain - Handle the OTP (level) domain option */ static ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env, diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 6d44a245e4..2fbc0dddad 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -3112,37 +3112,6 @@ api_to_connect_tcp_await_timeout3([Sock|Socka]) -> (catch socket:close(Sock)), api_to_connect_tcp_await_timeout3(Socka). -%% api_to_connect_tcp_await_timeout(Socks, To, ServerSA) -> -%% api_to_connect_tcp_await_timeout(Socks, To, ServerSA, 1). - -%% api_to_connect_tcp_await_timeout([], _To, _ServerSA, _ID) -> -%% ?FAIL(unexpected_success); -%% api_to_connect_tcp_await_timeout([Sock|Socks], To, ServerSA, ID) -> -%% ?SEV_IPRINT("~w: try connect", [ID]), -%% Start = t(), -%% case socket:connect(Sock, ServerSA, To) of -%% {error, timeout} -> -%% ?SEV_IPRINT("expected timeout (~w)", [ID]), -%% Stop = t(), -%% TDiff = tdiff(Start, Stop), -%% if -%% (TDiff >= To) -> -%% ok; -%% true -> -%% {error, {unexpected_timeout, TDiff, To}} -%% end; -%% {error, econnreset = Reason} -> -%% ?SEV_IPRINT("failed connecting: ~p - giving up", [Reason]), -%% ok; -%% {error, Reason} -> -%% ?SEV_EPRINT("failed connecting: ~p", [Reason]), -%% ?FAIL({connect, Reason}); -%% ok -> -%% ?SEV_IPRINT("unexpected success (~w) - try next", [ID]), -%% api_to_connect_tcp_await_timeout(Socks, To, ServerSA, ID+1) -%% end. - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -6866,6 +6835,12 @@ sc_rc_tcp_client_create(Domain) -> i("sc_rc_tcp_client_create -> entry"), case socket:open(Domain, stream, tcp) of {ok, Sock} -> + case socket:getopt(Sock, otp, fd) of + {ok, FD} -> + put(sname, f("rclient-~w", [FD])); % Update SName + _ -> + ok + end, Sock; {error, Reason} -> exit({open_failed, Reason}) @@ -6884,10 +6859,11 @@ sc_rc_tcp_client_bind(Sock, Domain) -> end. sc_rc_tcp_client_announce_ready(Parent, Slogan) -> + ?SEV_IPRINT("ready ~w", [Slogan]), ?SEV_ANNOUNCE_READY(Parent, Slogan). sc_rc_tcp_client_await_continue(Parent, Slogan) -> - i("sc_rc_tcp_client_await_continue -> entry"), + ?SEV_IPRINT("await ~w continue", [Slogan]), ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan). sc_rc_tcp_client_connect(Sock, ServerSA) -> @@ -6927,15 +6903,15 @@ sc_rc_tcp_handler_start(ID, Recv, Sock) -> Pid. sc_rc_tcp_handler(ID, Parent, Recv, Sock) -> - sc_rc_tcp_handler_init(ID, Parent), + sc_rc_tcp_handler_init(ID, socket:getopt(Sock, otp, fd), Parent), sc_rc_tcp_handler_await(Parent, recv), RecvRes = sc_rc_tcp_handler_recv(Recv, Sock), sc_rc_tcp_handler_announce_ready(Parent, recv, RecvRes), Reason = sc_rc_tcp_handler_await(Parent, terminate), exit(Reason). -sc_rc_tcp_handler_init(ID, Parent) -> - put(sname, f("handler-~w", [ID])), +sc_rc_tcp_handler_init(ID, {ok, FD}, Parent) -> + put(sname, f("handler-~w:~w", [ID, FD])), _MRef = erlang:monitor(process, Parent), ?SEV_IPRINT("started"), ?SEV_ANNOUNCE_READY(Parent, init), diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index ddd50fdefa..06e7c2910d 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 2e295a91ae..839087ef2a 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -41,12 +41,10 @@ send/2, send/3, send/4, sendto/3, sendto/4, sendto/5, sendmsg/2, sendmsg/3, sendmsg/4, - %% writev/4, OR SENDV? It will be strange for recv then: recvv (instead of readv) recv/1, recv/2, recv/3, recv/4, recvfrom/1, recvfrom/2, recvfrom/3, recvfrom/4, recvmsg/1, recvmsg/2, recvmsg/3, recvmsg/5, - %% readv/3, close/1, shutdown/2, @@ -164,16 +162,6 @@ 0..65535, 0..65535}. -%% -%% -%% Should we do these as maps instead? -%% If we do we may need to include the family (domain) in the -%% map (as the native type do. See struct sockaddr_in6). -%% -%% What about default values? Such as for port (=0) and addr (=any)? -%% -%% - -type timeval() :: #{sec := integer(), usec := integer()}. @@ -183,7 +171,7 @@ addr := ip4_address() % Header Destination address }. -%% If the integer value is used its up to the caller to ensure its valid! +%% If the integer value is used, its up to the caller to ensure its valid! -type ip_tos() :: lowdeley | throughput | reliability | @@ -326,10 +314,10 @@ -type otp_socket_option() :: debug | iow | controlling_process | - rcvbuf | - sndbuf | + rcvbuf | % sndbuf | rcvctrlbuf | - sndctrlbuf. + sndctrlbuf | + fd. %% Shall we have special treatment of linger?? %% read-only options: %% domain | protocol | type. @@ -653,6 +641,7 @@ %%-define(SOCKET_OPT_OTP_SNDBUF, 5). -define(SOCKET_OPT_OTP_RCVCTRLBUF, 6). -define(SOCKET_OPT_OTP_SNDCTRLBUF, 7). +-define(SOCKET_OPT_OTP_FD, 8). -define(SOCKET_OPT_OTP_DOMAIN, 16#FF01). % INTERNAL -define(SOCKET_OPT_OTP_TYPE, 16#FF02). % INTERNAL -define(SOCKET_OPT_OTP_PROTOCOL, 16#FF03). % INTERNAL @@ -3051,6 +3040,8 @@ enc_sockopt_key(otp, rcvctrlbuf, _, _, _, _) -> ?SOCKET_OPT_OTP_RCVCTRLBUF; enc_sockopt_key(otp, sndctrlbuf, _, _, _, _) -> ?SOCKET_OPT_OTP_SNDCTRLBUF; +enc_sockopt_key(otp, fd, get = _Dir, _, _, _) -> + ?SOCKET_OPT_OTP_FD; enc_sockopt_key(otp = L, Opt, _, _, _, _) -> not_supported({L, Opt}); -- cgit v1.2.3