Remove forced GC finalisation and make teardown deterministic / non-allocating

* Test change for memory issue
This commit is contained in:
abraunegg 2025-12-25 09:45:55 +11:00
commit 200c32f1b4
3 changed files with 20 additions and 35 deletions

View file

@ -622,10 +622,6 @@ class CurlEngine {
object.destroy(http); // Destroy, however we cant set to null
if ((debugLogging) && (debugHTTPSResponse)) {addLogEntry("Stopped HTTP instance shutdown and destroyed: " ~ to!string(internalThreadId), ["debug"]);}
}
// Perform Garbage Collection
GC.collect();
// Return free memory to the OS
GC.minimize();
}
// Disable SSL certificate peer verification for libcurl operations.
@ -770,10 +766,6 @@ void releaseAllCurlInstances() {
curlEnginePool.length = 0; // More explicit than curlEnginePool = [];
}
}
// Perform Garbage Collection on the destroyed curl engines
GC.collect();
// Return free memory to the OS
GC.minimize();
// Log that all curl engines have been released
if ((debugLogging) && (debugHTTPSResponse)) {addLogEntry("CurlEngine releaseAllCurlInstances() completed", ["debug"]);}
}

View file

@ -40,11 +40,20 @@ private struct WsFrame {
ubyte[] payload;
}
private enum long CURL_GLOBAL_DEFAULT = 3;
shared static this() {
curl_global_init(CURL_GLOBAL_DEFAULT);
}
shared static ~this() {
curl_global_cleanup();
}
final class CurlWebSocket {
private:
// libcurl constants defined locally
enum long CURL_GLOBAL_DEFAULT = 3;
enum int CURLOPT_URL = 10002;
enum int CURLOPT_FOLLOWLOCATION = 52;
enum int CURLOPT_NOSIGNAL = 99;
@ -87,7 +96,6 @@ private:
public:
this() {
websocketConnected = false;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
rng = Random(unpredictableSeed);
logCurlWebsocketOutput("Created a new instance of a CurlWebSocket object accessing libcurl for HTTP operations");
@ -96,13 +104,10 @@ public:
~this() {
if (curl !is null) {
curl_easy_cleanup(curl);
curl = null;
}
curl_global_cleanup();
websocketConnected = false;
object.destroy(curl);
logCurlWebsocketOutput("Destroyed 'curl' object");
curl = null;
logCurlWebsocketOutput("Destroyed instance of a CurlWebSocket object accessing libcurl for HTTP operations");
logCurlWebsocketOutput("Cleaned-up an instance of a CurlWebSocket object accessing libcurl for HTTP operations");
}
bool isConnected() {
@ -110,8 +115,8 @@ public:
}
void setTimeouts(int connectMs, int rwMs) {
connectTimeoutMs = connectMs;
ioTimeoutMs = rwMs;
this.connectTimeoutMs = connectMs;
this.ioTimeoutMs = rwMs;
}
void setUserAgent(string ua) {
@ -119,7 +124,7 @@ public:
}
void setHTTPSDebug(bool httpsDebug) {
httpsDebug = httpsDebug;
this.httpsDebug = httpsDebug;
}
int connect(string wsUrl) {
@ -140,9 +145,10 @@ public:
pathQuery = p.pathQuery;
string connectUrl = (scheme == "wss" ? "https://" : "http://") ~ hostPort ~ pathQuery;
curl_easy_reset(curl);
// Reset
curl_easy_reset(curl);
// Configure curl options
curl_easy_setopt(curl, cast(int)CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, cast(int)CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, cast(int)CURLOPT_USERAGENT, userAgent.toStringz); // NUL-terminated

View file

@ -466,7 +466,7 @@ bool testInternetReachability(ApplicationConfig appConfig, bool displayLogging =
// Explicitly set to ensure the connection get closed at once after use
// https://curl.se/libcurl/c/CURLOPT_FORBID_REUSE.html
http.handle.set(CurlOption.forbid_reuse,0);
http.handle.set(CurlOption.forbid_reuse,1);
// Set HTTP method to HEAD for minimal data transfer
http.method = HTTP.Method.head;
@ -475,13 +475,8 @@ bool testInternetReachability(ApplicationConfig appConfig, bool displayLogging =
// Exit scope to ensure cleanup
scope(exit) {
// Shut http down and destroy
// Ensure everything is shutdown cleanly
http.shutdown();
object.destroy(http);
// Perform Garbage Collection
GC.collect();
// Return free memory to the OS
GC.minimize();
}
// Execute the request and handle exceptions
@ -515,14 +510,6 @@ bool testInternetReachability(ApplicationConfig appConfig, bool displayLogging =
reachedService = false;
}
// Ensure everything is shutdown cleanly
http.shutdown();
object.destroy(http);
// Perform Garbage Collection
GC.collect();
// Return free memory to the OS
GC.minimize();
// Return state
return reachedService;
}