Update PR

* Add debug logging for HTTP Response Headers
* Add debug logging for HTTP Status Line
* Ensure all logging is flushed correctly and log buffers are flushed
* Use forceExit(); in a consistent manner, which shuts down logging and flushes any remaining logs in buffer
This commit is contained in:
abraunegg 2024-05-11 08:20:01 +10:00
parent 00205bf2bd
commit 1eb089ae58
7 changed files with 44 additions and 25 deletions

View file

@ -65,6 +65,8 @@ class CurlResponse {
hasResponse = true;
this.responseHeaders = http.responseHeaders();
this.statusLine = http.statusLine;
addLogEntry("HTTP Response Headers: " ~ to!string(this.responseHeaders), ["debug"]);
addLogEntry("HTTP Status Line: " ~ to!string(this.statusLine), ["debug"]);
}
@safe pure HTTP.StatusLine getStatus() {
@ -92,23 +94,26 @@ class CurlResponse {
const string parseRequestHeaders(const(const(char)[][const(char)[]]) headers) {
string requestHeadersStr = "";
foreach (string header; headers.byKey()) {
if (header == "Authorization") {
continue;
}
// Use the 'in' operator to safely check if the key exists in the associative array.
if (auto val = header in headers) {
requestHeadersStr ~= "< " ~ header ~ ": " ~ *val ~ "\n";
// Ensure response headers is not null and iterate over keys safely.
if (headers !is null) {
foreach (string header; headers.byKey()) {
if (header == "Authorization") {
continue;
}
// Use the 'in' operator to safely check if the key exists in the associative array.
if (auto val = header in headers) {
requestHeadersStr ~= "< " ~ header ~ ": " ~ *val ~ "\n";
}
}
}
return requestHeadersStr;
}
const string parseResponseHeaders(const(immutable(char)[][immutable(char)[]]) headers) {
const string parseResponseHeaders(const(string[string]) headers) {
string responseHeadersStr = "";
// Ensure response headers is not null and iterate over keys safely.
if (headers !is null) {
foreach (const(char)[] header; headers.byKey()) {
foreach (string header; headers.byKey()) {
// Check if the key actually exists before accessing it to avoid RangeError.
if (auto val = header in headers) { // 'in' checks for the key and returns a pointer to the value if found.
responseHeadersStr ~= "> " ~ header ~ ": " ~ *val ~ "\n"; // Dereference pointer to get the value.

View file

@ -60,11 +60,18 @@ class LogBuffer {
isRunning = false;
condReady.notifyAll(); // Wake up all waiting threads
}
// Wait for the flush thread to finish outside of the synchronized block to avoid deadlocks
if (flushThread.isRunning()) {
// Flush any remaining log
flushBuffer();
// Join all threads
flushThread.join();
}
// Flush anything remaining
flush(); // Perform a final flush to ensure all data is processed
flushBuffer(); // Finally flush the buffers one last time
}
shared void logThisMessage(string message, string[] levels = ["info"]) {

View file

@ -432,8 +432,8 @@ final class Monitor {
addLogEntry(" Error Message: " ~ e.msg);
addLogEntry("ACCESS ERROR: Please check your UID and GID access to this file, as the permissions on this file is preventing this application to read it");
addLogEntry("\nFATAL: Forcing exiting application to avoid deleting data due to local file system access issues\n");
// Must exit here
exit(-1);
// Must force exit here, allow logging to be done
forceExit();
} else {
// some other error
displayFileSystemErrorMessage(e.msg, getFunctionName!({}));

View file

@ -418,15 +418,13 @@ class OneDriveApi {
// display the error message
displayFileSystemErrorMessage(exception.msg, getFunctionName!({}));
// Must force exit here, allow logging to be done
Thread.sleep(dur!("msecs")(500));
exit(-1);
forceExit();
} catch (ErrnoException exception) {
// There was a file system error
// display the error message
displayFileSystemErrorMessage(exception.msg, getFunctionName!({}));
// Must force exit here, allow logging to be done
Thread.sleep(dur!("msecs")(500));
exit(-1);
forceExit();
}
addLogEntry("Client requires authentication before proceeding. Waiting for --auth-files elements to be available.");

View file

@ -10,6 +10,7 @@ import std.conv;
// What other modules that we have created do we need to import?
import log;
import util;
extern (C) immutable(char)* sqlite3_errstr(int); // missing from the std library
@ -72,14 +73,16 @@ struct Database {
addLogEntry("The database cannot be opened. Please check the permissions of " ~ to!string(filename));
addLogEntry();
close();
exit(-1);
// Must force exit here, allow logging to be done
forceExit();
}
if (rc != SQLITE_OK) {
addLogEntry();
addLogEntry("A database access error occurred: " ~ getErrorMessage());
addLogEntry();
close();
exit(-1);
// Must force exit here, allow logging to be done
forceExit();
}
sqlite3_extended_result_codes(pDb, 1); // always use extended result codes
}
@ -94,7 +97,8 @@ struct Database {
addLogEntry("Please retry your command with --resync to fix any local database corruption issues.");
addLogEntry();
close();
exit(-1);
// Must force exit here, allow logging to be done
forceExit();
}
}
@ -190,7 +194,8 @@ struct Statement {
addLogEntry();
addLogEntry("Please retry your command with --resync to fix any local database corruption issues.");
addLogEntry();
exit(-1);
// Must force exit here, allow logging to be done
forceExit();
}
}
}

View file

@ -5804,6 +5804,7 @@ class SyncEngine {
flagAsBigDelete = true;
if (!appConfig.getValueBool("force")) {
addLogEntry("ERROR: An attempt to remove a large volume of data from OneDrive has been detected. Exiting client to preserve data on Microsoft OneDrive");
addLogEntry("ERROR: The total number of items being deleted is: " ~ to!string(itemsToDelete));
addLogEntry("ERROR: To delete a large volume of data use --force or increase the config value 'classify_as_big_delete' to a larger value");
// Must exit here to preserve data on online , allow logging to be done
forceExit();

View file

@ -637,8 +637,7 @@ void handleClientUnauthorised(int httpStatusCode, string message) {
}
// Must force exit here, allow logging to be done
Thread.sleep(dur!("msecs")(500));
exit(EXIT_FAILURE);
forceExit();
}
// Parse and display error message received from the local file system
@ -659,8 +658,7 @@ void displayFileSystemErrorMessage(string message, string callingFunction) {
ulong localActualFreeSpace = to!ulong(getAvailableDiskSpace("."));
if (localActualFreeSpace == 0) {
// Must force exit here, allow logging to be done
Thread.sleep(dur!("msecs")(500));
exit(EXIT_FAILURE);
forceExit();
}
} catch (Exception e) {
// Handle exceptions from disk space check or type conversion
@ -1193,10 +1191,15 @@ int calc_eta(size_t counter, size_t iterations, ulong start_time) {
}
}
// Force Exit
// Force Exit due to failure
void forceExit() {
// Allow logging to flush and complete
// Allow any logging complete before we force exit
Thread.sleep(dur!("msecs")(500));
// Shutdown logging, which also flushes all logging buffers
(cast() logBuffer).shutdown();
object.destroy(logBuffer);
// Force Exit
exit(EXIT_FAILURE);
}