File 0343-observer-Reading-invalid-port-socket-options.patch of Package erlang

From ff80ff54467cd21e2f8abb713b66df6de773a169 Mon Sep 17 00:00:00 2001
From: Micael Karlberg <bmk@erlang.org>
Date: Wed, 30 Mar 2022 14:44:51 +0200
Subject: [PATCH 1/5] [observer] Reading invalid port socket options

Reading port socket options is now done "individually".
This means that if one option is invalid its simply skipped,
and we continue with the rest.

OTP-18012
---
 lib/runtime_tools/src/observer_backend.erl | 47 +++++++++++++++++-----
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index ecbba3d0d8..1bdfb6fb9b 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -205,15 +205,7 @@ inet_port_extra({_,Type},Port) when Type =:= "udp_inet";
                 [{local_address,LAddr}];
             {error, _} -> []
         end ++
-        case inet:getopts(Port,
-                          [active, broadcast, buffer, bind_to_device,
-                           delay_send, deliver, dontroute, exit_on_close,
-                           header, high_msgq_watermark, high_watermark,
-                           ipv6_v6only, keepalive, linger, low_msgq_watermark,
-                           low_watermark, mode, netns, nodelay, packet,
-                           packet_size, priority, read_packets, recbuf,
-                           reuseaddr, send_timeout, send_timeout_close,
-                           show_econnreset, sndbuf, tos, tclass]) of
+        case get_sock_opts(Port) of
             {ok, Opts} -> [{options, Opts}];
             {error, _} -> []
         end,
@@ -221,6 +213,43 @@ inet_port_extra({_,Type},Port) when Type =:= "udp_inet";
 inet_port_extra(_,_) ->
     [].
 
+sock_opts() ->
+    [active, broadcast, buffer, bind_to_device,
+     delay_send, deliver, dontroute, exit_on_close,
+     header, high_msgq_watermark, high_watermark,
+     ipv6_v6only, keepalive, linger, low_msgq_watermark,
+     low_watermark, mode, netns, nodelay, packet,
+     packet_size, priority, read_packets, recbuf,
+     reuseaddr, send_timeout, send_timeout_close,
+     show_econnreset, sndbuf, tos, tclass].
+
+get_sock_opts(Port) ->
+    get_sock_opts(Port, sock_opts()).
+
+get_sock_opts(Port, Opts) ->
+    get_sock_opts(Port, Opts, []).
+
+%% The reason we are doing it this way, is because if there
+%% is an issue with one of the options, we should just skip
+%% that option and continue with the next.
+%% Better to have some options then none.
+get_sock_opts(_Port, [], Acc) ->
+    {ok, lists:reverse(Acc)};
+get_sock_opts(Port, [Opt|Opts], Acc) ->
+    case inet:getopts(Port, [Opt]) of
+        {ok, [Res]} ->
+            get_sock_opts(Port, Opts, [Res|Acc]);
+        {ok, []} -> % No value?
+            get_sock_opts(Port, Opts, Acc);
+        {error, einval} ->
+            get_sock_opts(Port, Opts, Acc);
+
+        %% If the option is "invalid", the reason would be 'einval',
+        %% so this error must be something else => fail
+        {error, _} = ERROR ->
+            ERROR
+    end.
+
 
 get_socket_list() ->
     GetOpt = fun(_Sock, {Opt, false}) ->
-- 
2.34.1

openSUSE Build Service is sponsored by