Skip to content

Commit

Permalink
liana: remove the daemon feature
Browse files Browse the repository at this point in the history
We expect user to use systemd service to manage a daemon or
to handle their process by themself.

The json-rpc server is exposed only for unix systems through
unix sockets, it is moved to its own module while the implementation
for windows is marked as TODO.
  • Loading branch information
edouardparis committed Nov 18, 2024
1 parent 1b00cdf commit 6ce083e
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 156 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 0 additions & 7 deletions liana/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,12 @@ exclude = [".github/", ".cirrus.yml", "tests/", "test_data/", "contrib/", "pypr
[[bin]]
name = "lianad"
path = "src/bin/daemon.rs"
required-features = ["daemon"]

[[bin]]
name = "liana-cli"
path = "src/bin/cli.rs"
required-features = ["daemon"]

[features]
default = ["daemon"]
daemon = ["libc"]
nonblocking_shutdown = []

[dependencies]
Expand Down Expand Up @@ -59,9 +55,6 @@ rusqlite = { version = "0.30", features = ["bundled", "unlock_notify"] }
# To talk to bitcoind
jsonrpc = { version = "0.17", features = ["minreq_http"], default-features = false }

# Used for daemonization
libc = { version = "0.2", optional = true }

# Used for generating mnemonics
getrandom = "0.2"

Expand Down
7 changes: 1 addition & 6 deletions liana/src/bin/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,7 @@ fn main() {
process::exit(1);
});

let handle = DaemonHandle::start_default(
config,
#[cfg(all(unix, feature = "daemon"))]
true,
)
.unwrap_or_else(|e| {
let handle = DaemonHandle::start_default(config, cfg!(unix)).unwrap_or_else(|e| {
log::error!("Error starting Liana daemon: {}", e);
process::exit(1);
});
Expand Down
69 changes: 0 additions & 69 deletions liana/src/daemonize.rs

This file was deleted.

31 changes: 31 additions & 0 deletions liana/src/jsonrpc/server/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#[cfg(unix)]
mod unix;

use std::{
io, path,
sync::{atomic::AtomicBool, Arc},
};

use crate::DaemonControl;

#[cfg(unix)]
pub fn run(
socket_path: &path::Path,
daemon_control: DaemonControl,
shutdown: Arc<AtomicBool>,
) -> Result<(), io::Error> {
let listener = unix::rpcserver_setup(socket_path)?;
log::info!("JSONRPC server started.");
let res = unix::rpcserver_loop(listener, daemon_control, shutdown);
log::info!("JSONRPC server stopped.");
res
}

#[cfg(windows)]
pub fn run(
_socket_path: &path::Path,
_daemon_control: DaemonControl,
_shutdown: Arc<AtomicBool>,
) -> Result<(), io::Error> {
todo!("Implement a json rpc server over Named pipe");
}
20 changes: 8 additions & 12 deletions liana/src/jsonrpc/server.rs → liana/src/jsonrpc/server/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::{
};

use std::{
io,
os::unix::net,
fs, io,
os::unix::{fs::PermissionsExt, net},
path,
sync::{self, atomic},
thread, time,
Expand Down Expand Up @@ -194,17 +194,13 @@ fn bind(socket_path: &path::Path) -> Result<net::UnixListener, io::Error> {
pub fn rpcserver_setup(socket_path: &path::Path) -> Result<net::UnixListener, io::Error> {
log::debug!("Binding socket at {}", socket_path.display());
// Create the socket with RW permissions only for the user
#[cfg(not(test))]
let old_umask = unsafe { libc::umask(0o177) };
#[allow(clippy::all)]
let listener = bind(socket_path);

#[cfg(not(test))]
unsafe {
libc::umask(old_umask);
}
let listener = bind(socket_path)?;

// Set the permissions to RW for the user only
let permissions = fs::Permissions::from_mode(0o600);
fs::set_permissions(socket_path, permissions)?;

listener
Ok(listener)
}

#[cfg(test)]
Expand Down
50 changes: 7 additions & 43 deletions liana/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
mod bitcoin;
pub mod commands;
pub mod config;
#[cfg(all(unix, feature = "daemon"))]
mod daemonize;
mod database;
pub mod descriptors;
#[cfg(all(unix, feature = "daemon"))]
mod jsonrpc;
pub mod random;
pub mod signer;
Expand All @@ -22,8 +19,8 @@ pub use crate::bitcoin::{
d::{BitcoinD, BitcoindError, WalletError},
electrum::{Electrum, ElectrumError},
};
#[cfg(all(unix, feature = "daemon"))]
use crate::jsonrpc::server::{rpcserver_loop, rpcserver_setup};

use crate::jsonrpc::server;
use crate::{
bitcoin::{poller, BitcoinInterface},
config::Config,
Expand Down Expand Up @@ -411,7 +408,6 @@ pub enum DaemonHandle {
poller_handle: thread::JoinHandle<()>,
control: DaemonControl,
},
#[cfg(feature = "daemon")]
Server {
poller_sender: mpsc::SyncSender<poller::PollerMessage>,
poller_handle: thread::JoinHandle<()>,
Expand All @@ -435,7 +431,7 @@ impl DaemonHandle {
config: Config,
bitcoin: Option<impl BitcoinInterface + 'static>,
db: Option<impl DatabaseInterface + 'static>,
#[cfg(all(unix, feature = "daemon"))] with_rpc_server: bool,
with_rpc_server: bool,
) -> Result<Self, StartupError> {
#[cfg(not(test))]
setup_panic_hook();
Expand Down Expand Up @@ -490,20 +486,6 @@ impl DaemonHandle {
(None, None) => Err(StartupError::MissingBitcoinBackendConfig)?,
};

// If we are on a UNIX system and they told us to daemonize, do it now.
// NOTE: it's safe to daemonize now, as we don't carry any open DB connection
// https://www.sqlite.org/howtocorrupt.html#_carrying_an_open_database_connection_across_a_fork_
#[cfg(all(unix, feature = "daemon"))]
if config.daemon {
log::info!("Daemonizing");
let log_file = data_dir.as_path().join("log");
let pid_file = data_dir.as_path().join("lianad.pid");
unsafe {
daemonize::daemonize(&data_dir, &log_file, &pid_file)
.map_err(StartupError::Daemonization)?;
}
}

// Start the poller thread. Keep the thread handle to be able to check if it crashed. Store
// an atomic to be able to stop it.
let mut bitcoin_poller =
Expand All @@ -525,7 +507,6 @@ impl DaemonHandle {
// structure or through the JSONRPC server we may setup below.
let control = DaemonControl::new(config, bit, poller_sender.clone(), db, secp);

#[cfg(all(unix, feature = "daemon"))]
if with_rpc_server {
let rpcserver_shutdown = sync::Arc::from(sync::atomic::AtomicBool::from(false));
let rpcserver_handle = thread::Builder::new()
Expand All @@ -535,11 +516,7 @@ impl DaemonHandle {
move || {
let mut rpc_socket = data_dir;
rpc_socket.push("lianad_rpc");
let listener = rpcserver_setup(&rpc_socket)?;
log::info!("JSONRPC server started.");

rpcserver_loop(listener, control, shutdown)?;
log::info!("JSONRPC server stopped.");
server::run(&rpc_socket, control, shutdown)?;
Ok(())
}
})
Expand All @@ -564,13 +541,12 @@ impl DaemonHandle {
/// and SQLite).
pub fn start_default(
config: Config,
#[cfg(all(unix, feature = "daemon"))] with_rpc_server: bool,
with_rpc_server: bool,
) -> Result<DaemonHandle, StartupError> {
Self::start(
config,
Option::<BitcoinD>::None,
Option::<SqliteDb>::None,
#[cfg(all(unix, feature = "daemon"))]
with_rpc_server,
)
}
Expand All @@ -583,7 +559,6 @@ impl DaemonHandle {
Self::Controller {
ref poller_handle, ..
} => !poller_handle.is_finished(),
#[cfg(feature = "daemon")]
Self::Server {
ref poller_handle,
ref rpcserver_handle,
Expand All @@ -606,7 +581,6 @@ impl DaemonHandle {
poller_handle.join().expect("Poller thread must not panic");
Ok(())
}
#[cfg(feature = "daemon")]
Self::Server {
poller_sender,
poller_handle,
Expand Down Expand Up @@ -867,12 +841,7 @@ mod tests {
let t = thread::spawn({
let config = config.clone();
move || {
let handle = DaemonHandle::start_default(
config,
#[cfg(all(unix, feature = "daemon"))]
false,
)
.unwrap();
let handle = DaemonHandle::start_default(config, false).unwrap();
handle.stop().unwrap();
}
});
Expand All @@ -892,12 +861,7 @@ mod tests {
let t = thread::spawn({
let config = config.clone();
move || {
let handle = DaemonHandle::start_default(
config,
#[cfg(all(unix, feature = "daemon"))]
false,
)
.unwrap();
let handle = DaemonHandle::start_default(config, false).unwrap();
handle.stop().unwrap();
}
});
Expand Down
23 changes: 5 additions & 18 deletions liana/src/testutils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ impl DummyLiana {
pub fn _new(
bitcoin_interface: impl BitcoinInterface + 'static,
database: impl DatabaseInterface + 'static,
#[cfg(all(unix, feature = "daemon"))] rpc_server: bool,
rpc_server: bool,
) -> DummyLiana {
let tmp_dir = tmp_dir();
fs::create_dir_all(&tmp_dir).unwrap();
Expand All @@ -569,20 +569,14 @@ impl DummyLiana {
bitcoin_config,
bitcoin_backend: None,
data_dir: Some(data_dir),
#[cfg(unix)]
daemon: false,
log_level: log::LevelFilter::Debug,
main_descriptor: desc,
};

let handle = DaemonHandle::start(
config,
Some(bitcoin_interface),
Some(database),
#[cfg(all(unix, feature = "daemon"))]
rpc_server,
)
.unwrap();
let handle =
DaemonHandle::start(config, Some(bitcoin_interface), Some(database), rpc_server)
.unwrap();
DummyLiana { tmp_dir, handle }
}

Expand All @@ -591,16 +585,10 @@ impl DummyLiana {
bitcoin_interface: impl BitcoinInterface + 'static,
database: impl DatabaseInterface + 'static,
) -> DummyLiana {
Self::_new(
bitcoin_interface,
database,
#[cfg(all(unix, feature = "daemon"))]
false,
)
Self::_new(bitcoin_interface, database, false)
}

/// Creates a new DummyLiana interface which also spins up an RPC server.
#[cfg(all(unix, feature = "daemon"))]
pub fn new_server(
bitcoin_interface: impl BitcoinInterface + 'static,
database: impl DatabaseInterface + 'static,
Expand All @@ -611,7 +599,6 @@ impl DummyLiana {
pub fn control(&self) -> &DaemonControl {
match self.handle {
DaemonHandle::Controller { ref control, .. } => control,
#[cfg(feature = "daemon")]
DaemonHandle::Server { .. } => unreachable!(),
}
}
Expand Down

0 comments on commit 6ce083e

Please sign in to comment.