mirror of
https://github.com/agessaman/MeshCore.git
synced 2026-08-28 21:38:23 +00:00
fix(mqtt): allocate the neighbors JSON buffer on first use, not at bridge start
allocateRuntimeBuffers() took NEIGHBORS_JSON_BUFFER_SIZE unconditionally on every board built WITH_MQTT_NEIGHBORS, whether or not mqtt.neighbors was ever turned on. On a non-PSRAM board that is 4 KB of internal DRAM held for the bridge's lifetime by a node that may never publish a neighbours snapshot. Gating the existing allocation on the pref would not work: mqtt.neighbors is read live by the mesh loop with no bridge restart, so enabling it at runtime would find no buffer and silently publish nothing. Allocate on first use instead, in requestPublishNeighbors(), which is reached only when something actually wants to publish — periodic or a manual discovery. Publishing the pointer across cores is safe with the existing handshake: the allocation precedes the release store on _neighbors_publish_pending, and the task loop reads the pointer only after its matching acquire load, so the pointer cannot be observed half-published. A failed allocation drops that one snapshot and retries on the next, rather than disabling neighbours for the bridge's lifetime as the eager path did. (cherry picked from commit e6da052a93f8765824d0fb4bd0c704ca3ed3d294)
This commit is contained in:
@@ -768,17 +768,10 @@ void MQTTBridge::allocateRuntimeBuffers() {
|
||||
_json_scratch_buffer ? "PSRAM" : "stack fallback");
|
||||
#endif
|
||||
|
||||
#if defined(WITH_MQTT_NEIGHBORS)
|
||||
// Persistent neighbors JSON buffer, heap-allocated on every board: too large to
|
||||
// keep inline in the bridge object the way the non-PSRAM status/packet buffers
|
||||
// are. psram_malloc() falls back to internal DRAM, so this works without PSRAM.
|
||||
// Unlike status/packet there is no stack fallback — a nullptr simply disables
|
||||
// publishing (requestPublishNeighbors/publishNeighbors both no-op on nullptr).
|
||||
_neighbors_json_buffer = static_cast<char*>(MQTTRuntimeBufferLifecycle::allocateIfMissing(
|
||||
_neighbors_json_buffer, NEIGHBORS_JSON_BUFFER_SIZE, psram_malloc));
|
||||
MQTT_DEBUG_PRINTLN("Neighbors buffer: %s",
|
||||
_neighbors_json_buffer ? "ready" : "unavailable");
|
||||
#endif
|
||||
// The neighbors JSON buffer is NOT allocated here — requestPublishNeighbors()
|
||||
// allocates it on first use, so a node with mqtt.neighbors off never pays its
|
||||
// 4 KB. mqtt.neighbors is read live with no bridge restart, so gating on the
|
||||
// pref here would leave a runtime enable with no buffer.
|
||||
}
|
||||
|
||||
void MQTTBridge::releaseRuntimeBuffers() {
|
||||
@@ -795,7 +788,7 @@ void MQTTBridge::releaseRuntimeBuffers() {
|
||||
_json_scratch_doc.clear();
|
||||
|
||||
#if defined(WITH_MQTT_NEIGHBORS)
|
||||
// Paired with the unconditional allocation in allocateRuntimeBuffers().
|
||||
// Paired with the lazy allocation in requestPublishNeighbors(); no-op if never used.
|
||||
_neighbors_json_buffer = static_cast<char*>(MQTTRuntimeBufferLifecycle::release(
|
||||
_neighbors_json_buffer, psram_free));
|
||||
_neighbors_publish_len = 0;
|
||||
@@ -3640,10 +3633,19 @@ void MQTTBridge::setNeighborsSchedule(NeighborsPhase phase, uint32_t secs_until_
|
||||
}
|
||||
|
||||
void MQTTBridge::requestPublishNeighbors(const char* json, size_t len) {
|
||||
if (!_neighbors_json_buffer || !json || len == 0) return;
|
||||
if (!json || len == 0) return;
|
||||
// Drop a new snapshot while one is still being published (Core 0 clears the
|
||||
// flag when done). Acquire pairs with the task loop's release store.
|
||||
if (_neighbors_publish_pending.load(std::memory_order_acquire)) return;
|
||||
// Allocated on first use so a node with neighbors off never pays the 4 KB.
|
||||
// Cross-core safe: the release store below publishes this pointer, and the task
|
||||
// loop only reads it after the matching acquire load.
|
||||
_neighbors_json_buffer = static_cast<char*>(MQTTRuntimeBufferLifecycle::allocateIfMissing(
|
||||
_neighbors_json_buffer, NEIGHBORS_JSON_BUFFER_SIZE, psram_malloc));
|
||||
if (!_neighbors_json_buffer) {
|
||||
MQTT_DEBUG_PRINTLN("Neighbors buffer unavailable, dropping snapshot");
|
||||
return;
|
||||
}
|
||||
if (len >= NEIGHBORS_JSON_BUFFER_SIZE) {
|
||||
len = NEIGHBORS_JSON_BUFFER_SIZE - 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user