mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-03 14:32:24 +02:00
Resolve segfault on exit
* As reported by @bpozdena , @aothmane-control - a segfault exists on exit, which has been tracked back to the threaded logging functions. This commit should resolve this segfault on exit. This commit has been developed and tested using Arch Linux: NAME="Arch Linux" PRETTY_NAME="Arch Linux" ID=arch BUILD_ID=rolling ANSI_COLOR="38;2;23;147;209" HOME_URL="https://archlinux.org/" DOCUMENTATION_URL="https://wiki.archlinux.org/" SUPPORT_URL="https://bbs.archlinux.org/" BUG_REPORT_URL="https://gitlab.archlinux.org/groups/archlinux/-/issues" PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/" LOGO=archlinux-logo Installed using archlinux-2024.05.01-x86_64.iso The version of 'ldc' that was installed, as detected by 'configure' was 1.37.0 ----------------------------------------- checking for a BSD-compatible install... /usr/bin/install -c checking for pkg-config... /usr/bin/pkg-config checking pkg-config is at least version 0.9.0... yes checking for dmd... no checking for ldc2... ldc2 checking version of D compiler... 1.37.0 checking for curl... yes checking for sqlite... yes checking for notify... yes configure: creating ./config.status config.status: creating Makefile config.status: creating contrib/pacman/PKGBUILD config.status: creating contrib/spec/onedrive.spec config.status: creating onedrive.1 config.status: creating contrib/systemd/onedrive.service config.status: creating contrib/systemd/onedrive@.service -----------------------------------------
This commit is contained in:
parent
e408145e08
commit
28a6dd7acc
2
configure
vendored
2
configure
vendored
|
@ -2007,7 +2007,7 @@ $as_echo "no" >&6; }
|
|||
fi
|
||||
fi
|
||||
|
||||
for ac_prog in dmd ldmd2 ldc2
|
||||
for ac_prog in dmd ldc2 ldmd2
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
|
|
22
src/log.d
22
src/log.d
|
@ -53,24 +53,21 @@ class LogBuffer {
|
|||
flushThread.start();
|
||||
}
|
||||
|
||||
// The destructor should only clean up resources owned directly by this instance
|
||||
~this() {
|
||||
object.destroy(bufferLock);
|
||||
object.destroy(condReady);
|
||||
object.destroy(flushThread);
|
||||
}
|
||||
|
||||
// Shutdown logging
|
||||
void shutdown() {
|
||||
synchronized(bufferLock) {
|
||||
if (!isRunning) return; // Prevent multiple shutdowns
|
||||
isRunning = false;
|
||||
condReady.notifyAll(); // Wake up all waiting threads
|
||||
}
|
||||
flushThread.join(); // Wait for the flush thread to finish
|
||||
// Wait for the flush thread to finish outside of the synchronized block to avoid deadlocks
|
||||
if (flushThread.isRunning()) {
|
||||
flushThread.join();
|
||||
}
|
||||
flush(); // Perform a final flush to ensure all data is processed
|
||||
}
|
||||
|
||||
shared void logThisMessage(string message, string[] levels = ["info"]) {
|
||||
|
||||
shared void logThisMessage(string message, string[] levels = ["info"]) {
|
||||
// Generate the timestamp for this log entry
|
||||
auto timeStamp = leftJustify(Clock.currTime().toString(), 28, '0');
|
||||
|
||||
|
@ -174,6 +171,11 @@ void addLogEntry(string message = "", string[] levels = ["info"]) {
|
|||
logBuffer.logThisMessage(message, levels);
|
||||
}
|
||||
|
||||
// Is logging still active
|
||||
bool loggingActive() {
|
||||
return logBuffer.isRunning;
|
||||
}
|
||||
|
||||
void addProcessingLogHeaderEntry(string message, long verbosityCount) {
|
||||
if (verbosityCount == 0) {
|
||||
addLogEntry(message, ["logFileOnly"]);
|
||||
|
|
19
src/main.d
19
src/main.d
|
@ -100,6 +100,7 @@ int main(string[] cliArgs) {
|
|||
addLogEntry("Exit scope was called", ["debug"]);
|
||||
// Perform synchronised exit
|
||||
performSynchronisedExitProcess("exitScope");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
scope(failure) {
|
||||
|
@ -107,6 +108,7 @@ int main(string[] cliArgs) {
|
|||
addLogEntry("Failure scope was called", ["debug"]);
|
||||
// Perform synchronised exit
|
||||
performSynchronisedExitProcess("failureScope");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Read in application options as passed in
|
||||
|
@ -774,7 +776,7 @@ int main(string[] cliArgs) {
|
|||
syncEngineInstance.scanLocalFilesystemPathForNewData(path);
|
||||
} catch (CurlException e) {
|
||||
addLogEntry("Offline, cannot create remote dir: " ~ path, ["verbose"]);
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
addLogEntry("Cannot create remote directory: " ~ e.msg, ["info", "notify"]);
|
||||
}
|
||||
}
|
||||
|
@ -796,13 +798,13 @@ int main(string[] cliArgs) {
|
|||
syncEngineInstance.deleteByPath(path);
|
||||
} catch (CurlException e) {
|
||||
addLogEntry("Offline, cannot delete item: " ~ path, ["verbose"]);
|
||||
} catch(SyncException e) {
|
||||
} catch (SyncException e) {
|
||||
if (e.msg == "The item to delete is not in the local database") {
|
||||
addLogEntry("Item cannot be deleted from Microsoft OneDrive because it was not found in the local database", ["verbose"]);
|
||||
} else {
|
||||
addLogEntry("Cannot delete remote item: " ~ e.msg, ["info", "notify"]);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
addLogEntry("Cannot delete remote item: " ~ e.msg, ["info", "notify"]);
|
||||
}
|
||||
};
|
||||
|
@ -820,7 +822,7 @@ int main(string[] cliArgs) {
|
|||
}
|
||||
} catch (CurlException e) {
|
||||
addLogEntry("Offline, cannot move item !", ["verbose"]);
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
addLogEntry("Cannot move item: " ~ e.msg, ["info", "notify"]);
|
||||
}
|
||||
};
|
||||
|
@ -1361,7 +1363,7 @@ extern(C) nothrow @nogc @system void exitHandler(int value) {
|
|||
|
||||
try {
|
||||
assumeNoGC ( () {
|
||||
addLogEntry("\nReceived termination signal, initiating cleanup");
|
||||
addLogEntry("\nReceived termination signal, initiating cleanup");
|
||||
// Wait for all parallel jobs that depend on the database to complete
|
||||
addLogEntry("Waiting for any existing upload|download process to complete");
|
||||
syncEngineInstance.shutdown();
|
||||
|
@ -1369,7 +1371,7 @@ extern(C) nothrow @nogc @system void exitHandler(int value) {
|
|||
// Perform the shutdown process
|
||||
performSynchronisedExitProcess("exitHandler");
|
||||
})();
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
// Any output here will cause a GC allocation
|
||||
// - Error: `@nogc` function `main.exitHandler` cannot call non-@nogc function `std.stdio.writeln!string.writeln`
|
||||
// - Error: cannot use operator `~` in `@nogc` function `main.exitHandler`
|
||||
|
@ -1408,7 +1410,10 @@ void performSynchronisedExitProcess(string scopeCaller = null) {
|
|||
}
|
||||
|
||||
// Finalise all logging and destroy log buffer
|
||||
shutdownApplicationLogging();
|
||||
if (loggingActive()) {
|
||||
// Shutdown application logging
|
||||
shutdownApplicationLogging();
|
||||
}
|
||||
|
||||
// Perform Garbage Cleanup
|
||||
GC.collect();
|
||||
|
|
10
src/sync.d
10
src/sync.d
|
@ -316,10 +316,10 @@ class SyncEngine {
|
|||
}
|
||||
|
||||
// The destructor should only clean up resources owned directly by this instance
|
||||
~this() {
|
||||
shutdownProcessPool();
|
||||
processPool = null;
|
||||
}
|
||||
//~this() {
|
||||
// //shutdownProcessPool();
|
||||
// processPool = null;
|
||||
//}
|
||||
|
||||
// Initialise the Sync Engine class
|
||||
bool initialise() {
|
||||
|
@ -425,13 +425,11 @@ class SyncEngine {
|
|||
// https://dlang.org/library/std/parallelism/task_pool.stop.html
|
||||
processPool.finish(); // If we flag 'true' here, the application segfaults on exit
|
||||
processPool.stop(); // Signals to all worker threads to terminate as soon as they are finished with their current Task, or immediately if they are not executing a Task.
|
||||
//processPool = new TaskPool(to!int(0)); // Reinitialise processPool to a zero size
|
||||
} else {
|
||||
// Normal TaskPool shutdown process
|
||||
addLogEntry("Shutting down processPool in a thread blocking manner", ["debug"]);
|
||||
processPool.finish(true); // If blocking argument is true, wait for all worker threads to terminate before returning.
|
||||
processPool.stop(); // Signals to all worker threads to terminate as soon as they are finished with their current Task, or immediately if they are not executing a Task.
|
||||
//processPool = new TaskPool(to!int(0)); // Reinitialise processPool to a zero size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue