fix(admin): stop the admin dispatcher from overflowing the ESP32 loopTask stack (#11239)
AdminModule::handleReceivedProtobuf carried a 3008-byte stack frame - 37% of the 8 KB Arduino loopTask stack. GCC inlines the eight handleGet* helpers into it, each of which builds a whole meshtastic_AdminMessage (480 B), so the dispatcher reserved a slot for every one of them at once even though only one case ever runs. Two more full AdminMessages lived directly in the function. That left any admin write short of stack for what runs beneath it: NodeDB::saveToDisk -> saveProto -> pb_encode -> SafeFile -> LittleFS -> flash. On heltec-v4 the canary fired at 7824 of 8192 bytes while writing /prefs/config.proto, so no setting ever persisted and the device rebooted. Mark the response builders NOINLINE and move the module-API and observer responses into their own functions. Pure refactor; measured on heltec-v4 the dispatcher frame drops 3008 -> 384 bytes, taking the crashing path from 368 bytes of headroom to 2992. Fixes #11237
This commit is contained in:
+31
-21
@@ -681,22 +681,41 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
#endif
|
||||
|
||||
default:
|
||||
meshtastic_AdminMessage res = meshtastic_AdminMessage_init_default;
|
||||
AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllModules(mp, r, &res);
|
||||
|
||||
if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE) {
|
||||
setPassKey(&res);
|
||||
myReply = allocDataProtobuf(res);
|
||||
} else if (mp.decoded.want_response) {
|
||||
LOG_DEBUG("Module API did not respond to admin message. req.variant=%d", r->which_payload_variant);
|
||||
} else if (handleResult != AdminMessageHandleResult::HANDLED) {
|
||||
// Probably a message sent by us or sent to our local node. FIXME, we should avoid scanning these messages
|
||||
LOG_DEBUG("Module API did not handle admin message %d", r->which_payload_variant);
|
||||
}
|
||||
handleViaModuleApi(mp, r);
|
||||
break;
|
||||
}
|
||||
|
||||
// Allow any observers (e.g. the UI) to handle/respond
|
||||
handleViaObservers(r);
|
||||
|
||||
// If asked for a response and it is not yet set, generate an 'ACK' response
|
||||
if (mp.decoded.want_response && !myReply) {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
|
||||
}
|
||||
if (mp.pki_encrypted && myReply) {
|
||||
myReply->pki_encrypted = true;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
void AdminModule::handleViaModuleApi(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *r)
|
||||
{
|
||||
meshtastic_AdminMessage res = meshtastic_AdminMessage_init_default;
|
||||
AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllModules(mp, r, &res);
|
||||
|
||||
if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE) {
|
||||
setPassKey(&res);
|
||||
myReply = allocDataProtobuf(res);
|
||||
} else if (mp.decoded.want_response) {
|
||||
LOG_DEBUG("Module API did not respond to admin message. req.variant=%d", r->which_payload_variant);
|
||||
} else if (handleResult != AdminMessageHandleResult::HANDLED) {
|
||||
// Probably a message sent by us or sent to our local node. FIXME, we should avoid scanning these messages
|
||||
LOG_DEBUG("Module API did not handle admin message %d", r->which_payload_variant);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleViaObservers(const meshtastic_AdminMessage *r)
|
||||
{
|
||||
AdminMessageHandleResult observerResult = AdminMessageHandleResult::NOT_HANDLED;
|
||||
meshtastic_AdminMessage observerResponse = meshtastic_AdminMessage_init_default;
|
||||
AdminModule_ObserverData observerData = {
|
||||
@@ -714,15 +733,6 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
} else if (observerResult == AdminMessageHandleResult::HANDLED) {
|
||||
LOG_DEBUG("Observer handled admin message");
|
||||
}
|
||||
|
||||
// If asked for a response and it is not yet set, generate an 'ACK' response
|
||||
if (mp.decoded.want_response && !myReply) {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
|
||||
}
|
||||
if (mp.pki_encrypted && myReply) {
|
||||
myReply->pki_encrypted = true;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
void AdminModule::handleGetModuleConfigResponse(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *r)
|
||||
|
||||
Reference in New Issue
Block a user