fix(mqtt): let a retried setup consume the reconnect allowance
reconnect_attempted_this_cycle is computed once before the maintenance loop and only maintainSlotConnection() was setting it. The deferred-setup retry armed the 15 s cross-slot guard via _last_slot_reconnect_ms but left the local flag false, so a disconnected slot later in the same pass still saw "no reconnect yet" and started a second TLS handshake. Two concurrent ~40 KB sessions is exactly the contention the guard prevents, and it landed in the one situation where internal heap is already known to be short -- a failed allocation is why the retry runs. Set on success only: setupSlot() returns true only after client->connect(), so success means a handshake was launched. A failed retry launches nothing and continues to spend only setup_retry_this_cycle, which rate-limits the allocation attempts without consuming the handshake allowance.
This commit is contained in:
1 parent
e242cc6fd3
commit
6be84eb4eb
1 file changed
+11
-1
@@ -2047,7 +2047,17 @@ void MQTTBridge::maintainSlotConnections() {
|
||||
setup_retry_this_cycle = true;
|
||||
MQTT_DEBUG_PRINTLN("MQTT%d retrying deferred setup (int_heap=%d)", i + 1,
|
||||
(int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
if (setupSlot(i)) _last_slot_reconnect_ms = now_millis;
|
||||
if (setupSlot(i)) {
|
||||
// A successful setup ends in connect(), so it spends this cycle's single
|
||||
// handshake allowance as well as arming the 15 s cross-slot guard. Without
|
||||
// the local flag, a disconnected slot later in this same pass would start a
|
||||
// second concurrent TLS handshake — the contention the guard exists to
|
||||
// prevent, and most damaging here because a failed allocation is why we are
|
||||
// retrying at all. A failed setup launches nothing and so spends only
|
||||
// setup_retry_this_cycle.
|
||||
_last_slot_reconnect_ms = now_millis;
|
||||
reconnect_attempted_this_cycle = true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user