Skip to content

Commit 6f76113

Browse files
MQTT: fix a very timing-sensitive issue around Last Will and expiration
When Will-Delay-Interval >= Session-Expiry-Interval, the will queue's x-expires and the will message TTL were only ~5 ms apart. Under a loaded scheduler the queue could be deleted before the dead-letter path ran, silently dropping the will. Extend x-expires by a fixed 1 s margin. Strictly additive; the SessionExpiry = infinity case is unchanged.
1 parent 8e90c42 commit 6f76113

1 file changed

Lines changed: 10 additions & 1 deletion

File tree

deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
-define(MAX_PERMISSION_CACHE_SIZE, 12).
4040
-define(CONSUMER_TAG, <<"mqtt">>).
4141
-define(QUEUE_TTL_KEY, <<"x-expires">>).
42+
-define(WILL_QUEUE_EXPIRY_MARGIN_MS, 1_000).
4243
-define(DEFAULT_EXCHANGE_NAME, <<>>).
4344
-define(FENCE_TIMEOUT, 30_000).
4445

@@ -1812,7 +1813,15 @@ maybe_send_will(
18121813
vhost = Vhost
18131814
}} = State)
18141815
when is_integer(Delay) andalso Delay > 0 andalso SessionExpiry > 0 ->
1815-
QArgs0 = queue_ttl_args(SessionExpiry),
1816+
%% Extend x-expires by a small margin above the Session Expiry Interval
1817+
%% so that the queue-expiry timer cannot race with the message-TTL +
1818+
%% dead-letter path and silently drop the Will Message.
1819+
QArgs0 = case queue_ttl_args(SessionExpiry) of
1820+
[] ->
1821+
[];
1822+
[{Key, Type, TtlMs}] ->
1823+
[{Key, Type, TtlMs + ?WILL_QUEUE_EXPIRY_MARGIN_MS}]
1824+
end,
18161825
QArgs = QArgs0 ++ [{<<"x-dead-letter-exchange">>, longstr, XName},
18171826
{<<"x-dead-letter-routing-key">>, longstr, mqtt_to_amqp(Topic)}],
18181827
T = erlang:monotonic_time(millisecond),

0 commit comments

Comments
 (0)