mirror of
https://github.com/wled/WLED.git
synced 2025-07-23 02:36:39 +00:00
Fix AsyncClient hangs
This commit is contained in:
parent
230af48899
commit
de4b352495
@ -150,11 +150,18 @@ void HttpPullLightControl::addToConfig(JsonObject& root) {
|
|||||||
// Do the http request here. Note that we can not do https requests with the AsyncTCP library
|
// Do the http request here. Note that we can not do https requests with the AsyncTCP library
|
||||||
// We do everything Asynchronous, so all callbacks are defined here
|
// We do everything Asynchronous, so all callbacks are defined here
|
||||||
void HttpPullLightControl::checkUrl() {
|
void HttpPullLightControl::checkUrl() {
|
||||||
|
// Extra Inactivity check to see if AsyncCLient hangs
|
||||||
|
if (client != nullptr && ( millis() - lastActivityTime > inactivityTimeout ) ) {
|
||||||
|
DEBUG_PRINTLN(F("Inactivity detected, deleting client."));
|
||||||
|
delete client;
|
||||||
|
client = nullptr;
|
||||||
|
}
|
||||||
if (client != nullptr && client->connected()) {
|
if (client != nullptr && client->connected()) {
|
||||||
DEBUG_PRINTLN(F("We are still connected, do nothing"));
|
DEBUG_PRINTLN(F("We are still connected, do nothing"));
|
||||||
// Do nothing, Client is still connected
|
// Do nothing, Client is still connected
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client != nullptr) {
|
if (client != nullptr) {
|
||||||
// Delete previous client instance if exists, just to prevent any memory leaks
|
// Delete previous client instance if exists, just to prevent any memory leaks
|
||||||
DEBUG_PRINTLN(F("Delete previous instances"));
|
DEBUG_PRINTLN(F("Delete previous instances"));
|
||||||
@ -169,6 +176,7 @@ void HttpPullLightControl::checkUrl() {
|
|||||||
DEBUG_PRINTLN(F("Data received."));
|
DEBUG_PRINTLN(F("Data received."));
|
||||||
// Cast arg back to the usermod class instance
|
// Cast arg back to the usermod class instance
|
||||||
HttpPullLightControl *instance = (HttpPullLightControl *)arg;
|
HttpPullLightControl *instance = (HttpPullLightControl *)arg;
|
||||||
|
instance->lastActivityTime = millis(); // Update lastactivity time when data is received
|
||||||
// Convertert to Safe-String
|
// Convertert to Safe-String
|
||||||
char *strData = new char[len + 1];
|
char *strData = new char[len + 1];
|
||||||
strncpy(strData, (char*)data, len);
|
strncpy(strData, (char*)data, len);
|
||||||
@ -185,19 +193,18 @@ void HttpPullLightControl::checkUrl() {
|
|||||||
//Set the class-own client pointer to nullptr if its the current client
|
//Set the class-own client pointer to nullptr if its the current client
|
||||||
HttpPullLightControl *instance = static_cast<HttpPullLightControl*>(arg);
|
HttpPullLightControl *instance = static_cast<HttpPullLightControl*>(arg);
|
||||||
if (instance->client == c) {
|
if (instance->client == c) {
|
||||||
|
delete instance->client; // Delete the client instance
|
||||||
instance->client = nullptr;
|
instance->client = nullptr;
|
||||||
}
|
}
|
||||||
// Do not remove client here, it is maintained by AsyncClient
|
|
||||||
}, this);
|
}, this);
|
||||||
client->onTimeout([](void *arg, AsyncClient *c, uint32_t time) {
|
client->onTimeout([](void *arg, AsyncClient *c, uint32_t time) {
|
||||||
DEBUG_PRINTLN(F("Timeout"));
|
DEBUG_PRINTLN(F("Timeout"));
|
||||||
//Set the class-own client pointer to nullptr if its the current client
|
//Set the class-own client pointer to nullptr if its the current client
|
||||||
HttpPullLightControl *instance = static_cast<HttpPullLightControl*>(arg);
|
HttpPullLightControl *instance = static_cast<HttpPullLightControl*>(arg);
|
||||||
if (instance->client == c) {
|
if (instance->client == c) {
|
||||||
delete instance->client;
|
delete instance->client; // Delete the client instance
|
||||||
instance->client = nullptr;
|
instance->client = nullptr;
|
||||||
}
|
}
|
||||||
// Do not remove client here, it is maintained by AsyncClient
|
|
||||||
}, this);
|
}, this);
|
||||||
client->onError([](void *arg, AsyncClient *c, int8_t error) {
|
client->onError([](void *arg, AsyncClient *c, int8_t error) {
|
||||||
DEBUG_PRINTLN("Connection error occurred!");
|
DEBUG_PRINTLN("Connection error occurred!");
|
||||||
@ -222,6 +229,8 @@ void HttpPullLightControl::checkUrl() {
|
|||||||
DEBUG_PRINT(host);
|
DEBUG_PRINT(host);
|
||||||
DEBUG_PRINT(F(" via port "));
|
DEBUG_PRINT(F(" via port "));
|
||||||
DEBUG_PRINTLN((url.startsWith("https")) ? 443 : 80);
|
DEBUG_PRINTLN((url.startsWith("https")) ? 443 : 80);
|
||||||
|
// Update lastActivityTime just before sending the request
|
||||||
|
lastActivityTime = millis();
|
||||||
//Try to connect
|
//Try to connect
|
||||||
if (!client->connect(host.c_str(), (url.startsWith("https")) ? 443 : 80)) {
|
if (!client->connect(host.c_str(), (url.startsWith("https")) ? 443 : 80)) {
|
||||||
DEBUG_PRINTLN(F("Failed to initiate connection."));
|
DEBUG_PRINTLN(F("Failed to initiate connection."));
|
||||||
@ -272,6 +281,7 @@ void HttpPullLightControl::handleResponse(String& responseStr) {
|
|||||||
if (!requestJSONBufferLock(myLockId)) {
|
if (!requestJSONBufferLock(myLockId)) {
|
||||||
DEBUG_PRINT(F("ERROR: Can not request JSON Buffer Lock, number: "));
|
DEBUG_PRINT(F("ERROR: Can not request JSON Buffer Lock, number: "));
|
||||||
DEBUG_PRINTLN(myLockId);
|
DEBUG_PRINTLN(myLockId);
|
||||||
|
releaseJSONBufferLock(); // Just release in any case, maybe there was already a buffer lock
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,12 +60,14 @@ private:
|
|||||||
|
|
||||||
// Define constants
|
// Define constants
|
||||||
static const uint8_t myLockId = USERMOD_ID_HTTP_PULL_LIGHT_CONTROL ; // Used for the requestJSONBufferLock(id) function
|
static const uint8_t myLockId = USERMOD_ID_HTTP_PULL_LIGHT_CONTROL ; // Used for the requestJSONBufferLock(id) function
|
||||||
static const int16_t ackTimeout = 10000; // ACK timeout in milliseconds when doing the URL request
|
static const int16_t ackTimeout = 9000; // ACK timeout in milliseconds when doing the URL request
|
||||||
static const uint16_t rxTimeout = 10000; // RX timeout in milliseconds when doing the URL request
|
static const uint16_t rxTimeout = 9000; // RX timeout in milliseconds when doing the URL request
|
||||||
static const unsigned long FNV_offset_basis = 2166136261;
|
static const unsigned long FNV_offset_basis = 2166136261;
|
||||||
static const unsigned long FNV_prime = 16777619;
|
static const unsigned long FNV_prime = 16777619;
|
||||||
|
static const unsigned long inactivityTimeout = 30000; // When the AsyncClient is inactive (hanging) for this many milliseconds, we kill it
|
||||||
|
|
||||||
unsigned long lastCheck = 0; // Timestamp of last check
|
unsigned long lastCheck = 0; // Timestamp of last check
|
||||||
|
unsigned long lastActivityTime = 0; // Time of last activity of AsyncClient
|
||||||
String host; // Host extracted from the URL
|
String host; // Host extracted from the URL
|
||||||
String path; // Path extracted from the URL
|
String path; // Path extracted from the URL
|
||||||
String uniqueId; // Cached unique ID
|
String uniqueId; // Cached unique ID
|
||||||
@ -96,6 +98,7 @@ public:
|
|||||||
client->onConnect(nullptr);
|
client->onConnect(nullptr);
|
||||||
// Now it is safe to delete the client.
|
// Now it is safe to delete the client.
|
||||||
delete client; // This is safe even if client is nullptr.
|
delete client; // This is safe even if client is nullptr.
|
||||||
|
client = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
Loading…
x
Reference in New Issue
Block a user