Merge #623: lib: non-blocking daemon shutdown

2a6b775f607dc0b56be874807bd36427922ac681 lib: non-blocking daemon shutdown (Antoine Poinsot)

Pull request description:

  This makes it possible to trigger the shutdown of the daemon through the DaemonHandle, without having to block while waiting for the poller thread to join.

  Incidently, this allows to avoid having to move `self` which in turns allows to fix a GUI bug (see
  https://github.com/wizardsardine/liana/issues/622).

ACKs for top commit:
  edouardparis:
    ACK 2a6b775f607dc0b56be874807bd36427922ac681

Tree-SHA512: a443ba27f28b5f1acf602f5e4339400dda5a7b2c70c9d7c36df3dfccc32baf7a6ae2cf07fd17666c023e68b943c7961d2c61be8678bc9be1fad1bdeb7c7f1554
This commit is contained in:
Antoine Poinsot 2023-08-22 15:53:02 +02:00
commit bb8b618f8a
No known key found for this signature in database
GPG Key ID: E13FC145CD3F4304
3 changed files with 27 additions and 2 deletions

View File

@ -22,6 +22,7 @@ required-features = ["daemon"]
[features]
default = ["daemon"]
daemon = ["libc"]
nonblocking_shutdown = []
[dependencies]
# For managing transactions (it re-exports the bitcoin crate)

View File

@ -36,11 +36,23 @@ impl Poller {
Poller { shutdown, handle }
}
pub fn stop(self) {
pub fn trigger_stop(&self) {
self.shutdown.store(true, atomic::Ordering::Relaxed);
}
pub fn stop(self) {
self.trigger_stop();
self.handle.join().expect("The poller loop must not fail");
}
#[cfg(feature = "nonblocking_shutdown")]
pub fn is_stopped(&self) -> bool {
// Doc says "This might return true for a brief moment after the threads main function has
// returned, but before the thread itself has stopped running.". But it's not an issue for
// us, as long as the main poller function has returned we are good.
self.handle.is_finished()
}
#[cfg(test)]
pub fn test_stop(&mut self) {
self.shutdown.store(true, atomic::Ordering::Relaxed);

View File

@ -458,12 +458,24 @@ impl DaemonHandle {
Ok(())
}
// NOTE: this moves out the data as it should not be reused after shutdown
/// Shut down the Liana daemon.
pub fn shutdown(self) {
self.bitcoin_poller.stop();
}
/// Tell the daemon to shut down. This will return before the shutdown completes. The structure
/// must not be reused after triggering shutdown.
#[cfg(feature = "nonblocking_shutdown")]
pub fn trigger_shutdown(&self) {
self.bitcoin_poller.trigger_stop()
}
/// Whether the daemon has finished shutting down.
#[cfg(feature = "nonblocking_shutdown")]
pub fn shutdown_complete(&self) -> bool {
self.bitcoin_poller.is_stopped()
}
// We need a shutdown utility that does not move for implementing Drop for the DummyLiana
#[cfg(test)]
pub fn test_shutdown(&mut self) {