diff --git a/.gitignore b/.gitignore index f5636f9..0ef3cb5 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ test/nul /test/test_settings_manager /test/test_logger /test/test_integration +/test/tsan_output.txt # Logs logs diff --git a/src/WebServer.cpp b/src/WebServer.cpp index 87c18bc..db8a0c5 100644 --- a/src/WebServer.cpp +++ b/src/WebServer.cpp @@ -143,8 +143,23 @@ void WebServer::begin() kRouteUpdateSettings, [this](AsyncWebServerRequest *request, JsonVariant &json) { + bool alreadyPending = false; portENTER_CRITICAL(&pendingMutex); - bool alreadyPending = pendingSettingsUpdate; + if (pendingSettingsUpdate) + { + alreadyPending = true; + } + else + { + pendingSettingsDoc.clear(); + JsonObject src = json.as(); + JsonObject dst = pendingSettingsDoc.to(); + for (JsonPair kv : src) + { + dst[kv.key()] = kv.value(); + } + pendingSettingsUpdate = true; + } portEXIT_CRITICAL(&pendingMutex); if (alreadyPending) @@ -154,17 +169,6 @@ void WebServer::begin() return; } - portENTER_CRITICAL(&pendingMutex); - pendingSettingsDoc.clear(); - JsonObject src = json.as(); - JsonObject dst = pendingSettingsDoc.to(); - for (JsonPair kv : src) - { - dst[kv.key()] = kv.value(); - } - pendingSettingsUpdate = true; - portEXIT_CRITICAL(&pendingMutex); - request->send(200, "application/json", "{\"status\":\"ok\"}"); })); @@ -236,10 +240,9 @@ void WebServer::begin() statusEvents.onConnect([this](AsyncEventSourceClient *client) { if (statusEvents.count() > kMaxSSEClients) { - // Over limit - the library already added the client, so we - // just won't send data and it will be cleaned up on next sweep. - logger.logf("SSE client rejected (count=%d, max=%d)", + logger.logf("SSE client rejected: closing excess client (count=%d, max=%d)", statusEvents.count(), kMaxSSEClients); + client->close(); return; } client->send("connected", "init", millis(), 1000); @@ -523,7 +526,15 @@ void WebServer::processPendingCommands() if (jsonObj.containsKey("detection_grace_period_ms")) settingsManager.setDetectionGracePeriodMs(jsonObj["detection_grace_period_ms"].as()); if (jsonObj.containsKey("detection_ratio_threshold")) - settingsManager.setDetectionRatioThreshold(jsonObj["detection_ratio_threshold"].as()); + { + float threshold = jsonObj["detection_ratio_threshold"].as(); + // Accept legacy 0.0-1.0 ratio payloads as well as 0-100 percent. + if (threshold > 0.0f && threshold <= 1.0f) + { + threshold *= 100.0f; + } + settingsManager.setDetectionRatioThreshold(static_cast(threshold + 0.5f)); + } if (jsonObj.containsKey("detection_hard_jam_mm")) settingsManager.setDetectionHardJamMm(jsonObj["detection_hard_jam_mm"].as()); if (jsonObj.containsKey("detection_soft_jam_time_ms"))