Skip to content

Commit dcc6190

Browse files
ansdmergify[bot]
authored andcommitted
Make tcp send OTP 26 compatible
Follow up of #7913 and #7921 This commit uses the approach explained in erlang/otp#7130 (comment) We cannot use the macro `?OTP_RELEASE` since macros are evaluated at compile time. RabbitMQ can be compiled with OTP 25 and executed with OTP 26. Therefore, we use `erlang:system_info(otp_release)` instead. As `erlang:system_info/1` might be costly, we store the send function in persistent_term. For OTP 25, we use the "old tcp send workaround" (i.e. `erlang:port_command/2`) which avoids expensive selective receives. For OTP 26, we use `gen_tcp:send/2` which uses the optimised selective receive. Once the minimum required version becomes OTP 26, we can just switch to `gen_tcp:send/2` and delete the `inet_reply` handling code in the various RabbitMQ reader and writer processes. Note that `rabbit_net:port_command/2` is not only used by RabbitMQ server, but also by the AMQP 0.9.1 client. Therefore, instead of putting the OTP version (or send function) into persistent_term within the rabbit app, we just do it the first time `rabbit_net:port_command/2` is invoked. (`rabbit_common` is just a library without supervision hierarchy.) (cherry picked from commit 6b4d881)
1 parent 0d9c4df commit dcc6190

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

deps/rabbit_common/src/rabbit_net.erl

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,32 @@ port_command(Sock, Data) when ?IS_SSL(Sock) ->
168168
{error, Reason} -> erlang:error(Reason)
169169
end;
170170
port_command(Sock, Data) when is_port(Sock) ->
171-
erlang:port_command(Sock, Data).
171+
Fun = case persistent_term:get(rabbit_net_tcp_send, undefined) of
172+
undefined ->
173+
Rel = list_to_integer(erlang:system_info(otp_release)),
174+
%% gen_tcp:send/2 does a selective receive of
175+
%% {inet_reply, Sock, Status[, CallerTag]}
176+
F = if Rel >= 26 ->
177+
%% Selective receive is optimised:
178+
%% https://github.com/erlang/otp/issues/6455
179+
fun gen_tcp_send/2;
180+
Rel < 26 ->
181+
%% Avoid costly selective receive.
182+
fun erlang:port_command/2
183+
end,
184+
ok = persistent_term:put(rabbit_net_tcp_send, F),
185+
F;
186+
F ->
187+
F
188+
end,
189+
Fun(Sock, Data).
190+
191+
gen_tcp_send(Sock, Data) ->
192+
case gen_tcp:send(Sock, Data) of
193+
ok -> self() ! {inet_reply, Sock, ok},
194+
true;
195+
{error, Reason} -> erlang:error(Reason)
196+
end.
172197

173198
getopts(Sock, Options) when ?IS_SSL(Sock) ->
174199
ssl:getopts(Sock, Options);

0 commit comments

Comments
 (0)