mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
fix: avoid freezing the UI when enabling/disabling overdrive (#300)
This commit is contained in:
parent
d9553a91a1
commit
76e5c2bcc4
@ -463,7 +463,7 @@ impl<'a> Handler {
|
|||||||
.context("Failed to edit GPU config and set enabled power states")
|
.context("Failed to edit GPU config and set enabled power states")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_snapshot(&self) -> anyhow::Result<String> {
|
pub async fn generate_snapshot(&self) -> anyhow::Result<String> {
|
||||||
let datetime = chrono::Local::now().format("%Y%m%d-%H%M%S");
|
let datetime = chrono::Local::now().format("%Y%m%d-%H%M%S");
|
||||||
let out_path = format!("/tmp/LACT-sysfs-snapshot-{datetime}.tar.gz");
|
let out_path = format!("/tmp/LACT-sysfs-snapshot-{datetime}.tar.gz");
|
||||||
|
|
||||||
@ -516,10 +516,12 @@ impl<'a> Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let system_info = system::info()
|
let system_info = system::info()
|
||||||
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
.map(|info| serde_json::to_value(info).unwrap());
|
.map(|info| serde_json::to_value(info).unwrap());
|
||||||
let initramfs_type = match OS_RELEASE.as_ref() {
|
let initramfs_type = match OS_RELEASE.as_ref() {
|
||||||
Ok(os_release) => detect_initramfs_type(os_release)
|
Ok(os_release) => detect_initramfs_type(os_release)
|
||||||
|
.await
|
||||||
.map(|initramfs_type| serde_json::to_value(initramfs_type).unwrap()),
|
.map(|initramfs_type| serde_json::to_value(initramfs_type).unwrap()),
|
||||||
Err(err) => Some(err.to_string().into()),
|
Err(err) => Some(err.to_string().into()),
|
||||||
};
|
};
|
||||||
|
@ -78,7 +78,7 @@ pub async fn handle_stream(stream: UnixStream, handler: Handler) -> anyhow::Resu
|
|||||||
async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyhow::Result<Vec<u8>> {
|
async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyhow::Result<Vec<u8>> {
|
||||||
match request {
|
match request {
|
||||||
Request::Ping => ok_response(ping()),
|
Request::Ping => ok_response(ping()),
|
||||||
Request::SystemInfo => ok_response(system::info()?),
|
Request::SystemInfo => ok_response(system::info().await?),
|
||||||
Request::ListDevices => ok_response(handler.list_devices()),
|
Request::ListDevices => ok_response(handler.list_devices()),
|
||||||
Request::DeviceInfo { id } => ok_response(handler.get_device_info(id)?),
|
Request::DeviceInfo { id } => ok_response(handler.get_device_info(id)?),
|
||||||
Request::DeviceStats { id } => ok_response(handler.get_gpu_stats(id)?),
|
Request::DeviceStats { id } => ok_response(handler.get_gpu_stats(id)?),
|
||||||
@ -106,9 +106,9 @@ async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyho
|
|||||||
Request::SetEnabledPowerStates { id, kind, states } => {
|
Request::SetEnabledPowerStates { id, kind, states } => {
|
||||||
ok_response(handler.set_enabled_power_states(id, kind, states).await?)
|
ok_response(handler.set_enabled_power_states(id, kind, states).await?)
|
||||||
}
|
}
|
||||||
Request::EnableOverdrive => ok_response(system::enable_overdrive()?),
|
Request::EnableOverdrive => ok_response(system::enable_overdrive().await?),
|
||||||
Request::DisableOverdrive => ok_response(system::disable_overdrive()?),
|
Request::DisableOverdrive => ok_response(system::disable_overdrive().await?),
|
||||||
Request::GenerateSnapshot => ok_response(handler.generate_snapshot()?),
|
Request::GenerateSnapshot => ok_response(handler.generate_snapshot().await?),
|
||||||
Request::ConfirmPendingConfig(command) => {
|
Request::ConfirmPendingConfig(command) => {
|
||||||
ok_response(handler.confirm_pending_config(command)?)
|
ok_response(handler.confirm_pending_config(command)?)
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,15 @@ use std::{
|
|||||||
io::Write,
|
io::Write,
|
||||||
os::unix::prelude::PermissionsExt,
|
os::unix::prelude::PermissionsExt,
|
||||||
path::Path,
|
path::Path,
|
||||||
process::Command,
|
|
||||||
};
|
};
|
||||||
|
use tokio::process::Command;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
const PP_OVERDRIVE_MASK: u64 = 0x4000;
|
const PP_OVERDRIVE_MASK: u64 = 0x4000;
|
||||||
pub const PP_FEATURE_MASK_PATH: &str = "/sys/module/amdgpu/parameters/ppfeaturemask";
|
pub const PP_FEATURE_MASK_PATH: &str = "/sys/module/amdgpu/parameters/ppfeaturemask";
|
||||||
pub const MODULE_CONF_PATH: &str = "/etc/modprobe.d/99-amdgpu-overdrive.conf";
|
pub const MODULE_CONF_PATH: &str = "/etc/modprobe.d/99-amdgpu-overdrive.conf";
|
||||||
|
|
||||||
pub fn info() -> anyhow::Result<SystemInfo<'static>> {
|
pub async fn info() -> anyhow::Result<SystemInfo<'static>> {
|
||||||
let version = env!("CARGO_PKG_VERSION");
|
let version = env!("CARGO_PKG_VERSION");
|
||||||
let profile = if cfg!(debug_assertions) {
|
let profile = if cfg!(debug_assertions) {
|
||||||
"debug"
|
"debug"
|
||||||
@ -24,6 +24,7 @@ pub fn info() -> anyhow::Result<SystemInfo<'static>> {
|
|||||||
let kernel_output = Command::new("uname")
|
let kernel_output = Command::new("uname")
|
||||||
.arg("-r")
|
.arg("-r")
|
||||||
.output()
|
.output()
|
||||||
|
.await
|
||||||
.context("Could not read kernel version")?;
|
.context("Could not read kernel version")?;
|
||||||
let kernel_version = String::from_utf8(kernel_output.stdout)
|
let kernel_version = String::from_utf8(kernel_output.stdout)
|
||||||
.context("Invalid kernel version output")?
|
.context("Invalid kernel version output")?
|
||||||
@ -45,7 +46,7 @@ pub fn info() -> anyhow::Result<SystemInfo<'static>> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_overdrive() -> anyhow::Result<String> {
|
pub async fn enable_overdrive() -> anyhow::Result<String> {
|
||||||
let current_mask = read_current_mask()?;
|
let current_mask = read_current_mask()?;
|
||||||
|
|
||||||
let new_mask = current_mask | PP_OVERDRIVE_MASK;
|
let new_mask = current_mask | PP_OVERDRIVE_MASK;
|
||||||
@ -62,7 +63,7 @@ pub fn enable_overdrive() -> anyhow::Result<String> {
|
|||||||
file.write_all(conf.as_bytes())
|
file.write_all(conf.as_bytes())
|
||||||
.context("Could not write config")?;
|
.context("Could not write config")?;
|
||||||
|
|
||||||
let message = match regenerate_initramfs() {
|
let message = match regenerate_initramfs().await {
|
||||||
Ok(initramfs_type) => {
|
Ok(initramfs_type) => {
|
||||||
format!("Initramfs was successfully regenerated (detected type {initramfs_type:?})")
|
format!("Initramfs was successfully regenerated (detected type {initramfs_type:?})")
|
||||||
}
|
}
|
||||||
@ -72,10 +73,10 @@ pub fn enable_overdrive() -> anyhow::Result<String> {
|
|||||||
Ok(message)
|
Ok(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_overdrive() -> anyhow::Result<String> {
|
pub async fn disable_overdrive() -> anyhow::Result<String> {
|
||||||
if Path::new(MODULE_CONF_PATH).exists() {
|
if Path::new(MODULE_CONF_PATH).exists() {
|
||||||
fs::remove_file(MODULE_CONF_PATH).context("Could not remove module config file")?;
|
fs::remove_file(MODULE_CONF_PATH).context("Could not remove module config file")?;
|
||||||
match regenerate_initramfs() {
|
match regenerate_initramfs().await {
|
||||||
Ok(initramfs_type) => Ok(format!(
|
Ok(initramfs_type) => Ok(format!(
|
||||||
"Initramfs was successfully regenerated (detected type {initramfs_type:?})"
|
"Initramfs was successfully regenerated (detected type {initramfs_type:?})"
|
||||||
)),
|
)),
|
||||||
@ -98,15 +99,17 @@ fn read_current_mask() -> anyhow::Result<u64> {
|
|||||||
u64::from_str_radix(ppfeaturemask, 16).context("Invalid ppfeaturemask")
|
u64::from_str_radix(ppfeaturemask, 16).context("Invalid ppfeaturemask")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regenerate_initramfs() -> anyhow::Result<InitramfsType> {
|
async fn regenerate_initramfs() -> anyhow::Result<InitramfsType> {
|
||||||
let os_release = OS_RELEASE.as_ref().context("Could not detect distro")?;
|
let os_release = OS_RELEASE.as_ref().context("Could not detect distro")?;
|
||||||
match detect_initramfs_type(os_release) {
|
match detect_initramfs_type(os_release).await {
|
||||||
Some(initramfs_type) => {
|
Some(initramfs_type) => {
|
||||||
info!("Detected initramfs type {initramfs_type:?}, regenerating");
|
info!("Detected initramfs type {initramfs_type:?}, regenerating");
|
||||||
let result = match initramfs_type {
|
let result = match initramfs_type {
|
||||||
InitramfsType::Debian => run_command("update-initramfs", &["-u"]),
|
InitramfsType::Debian => run_command("update-initramfs", &["-u"]).await,
|
||||||
InitramfsType::Mkinitcpio => run_command("mkinitcpio", &["-P"]),
|
InitramfsType::Mkinitcpio => run_command("mkinitcpio", &["-P"]).await,
|
||||||
InitramfsType::Dracut => run_command("dracut", &["--regenerate-all", "--force"]),
|
InitramfsType::Dracut => {
|
||||||
|
run_command("dracut", &["--regenerate-all", "--force"]).await
|
||||||
|
}
|
||||||
};
|
};
|
||||||
result.map(|()| initramfs_type)
|
result.map(|()| initramfs_type)
|
||||||
}
|
}
|
||||||
@ -116,13 +119,18 @@ fn regenerate_initramfs() -> anyhow::Result<InitramfsType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn detect_initramfs_type(os_release: &OsRelease) -> Option<InitramfsType> {
|
pub(crate) async fn detect_initramfs_type(os_release: &OsRelease) -> Option<InitramfsType> {
|
||||||
let id_like: Vec<_> = os_release.id_like.split_whitespace().collect();
|
let id_like: Vec<_> = os_release.id_like.split_whitespace().collect();
|
||||||
|
|
||||||
if os_release.id == "debian" || id_like.contains(&"debian") {
|
if os_release.id == "debian" || id_like.contains(&"debian") {
|
||||||
Some(InitramfsType::Debian)
|
Some(InitramfsType::Debian)
|
||||||
} else if os_release.id == "arch" || id_like.contains(&"arch") {
|
} else if os_release.id == "arch" || id_like.contains(&"arch") {
|
||||||
if Command::new("mkinitcpio").arg("--version").output().is_ok() {
|
if Command::new("mkinitcpio")
|
||||||
|
.arg("--version")
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
Some(InitramfsType::Mkinitcpio)
|
Some(InitramfsType::Mkinitcpio)
|
||||||
} else {
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
@ -131,7 +139,12 @@ pub(crate) fn detect_initramfs_type(os_release: &OsRelease) -> Option<InitramfsT
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else if os_release.id == "fedora" {
|
} else if os_release.id == "fedora" {
|
||||||
if Command::new("dracut").arg("--version").output().is_ok() {
|
if Command::new("dracut")
|
||||||
|
.arg("--version")
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
Some(InitramfsType::Dracut)
|
Some(InitramfsType::Dracut)
|
||||||
} else {
|
} else {
|
||||||
warn!("Fedora without dracut detected, refusing to regenerate initramfs");
|
warn!("Fedora without dracut detected, refusing to regenerate initramfs");
|
||||||
@ -142,11 +155,12 @@ pub(crate) fn detect_initramfs_type(os_release: &OsRelease) -> Option<InitramfsT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_command(exec: &str, args: &[&str]) -> anyhow::Result<()> {
|
async fn run_command(exec: &str, args: &[&str]) -> anyhow::Result<()> {
|
||||||
info!("Running {exec} with args {args:?}");
|
info!("Running {exec} with args {args:?}");
|
||||||
let output = Command::new(exec)
|
let output = Command::new(exec)
|
||||||
.args(args)
|
.args(args)
|
||||||
.output()
|
.output()
|
||||||
|
.await
|
||||||
.context("Could not run command")?;
|
.context("Could not run command")?;
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -163,8 +177,8 @@ mod tests {
|
|||||||
use lact_schema::InitramfsType;
|
use lact_schema::InitramfsType;
|
||||||
use os_release::OsRelease;
|
use os_release::OsRelease;
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn detect_initramfs_debian() {
|
async fn detect_initramfs_debian() {
|
||||||
let data = r#"
|
let data = r#"
|
||||||
PRETTY_NAME="Debian GNU/Linux trixie/sid"
|
PRETTY_NAME="Debian GNU/Linux trixie/sid"
|
||||||
NAME="Debian GNU/Linux"
|
NAME="Debian GNU/Linux"
|
||||||
@ -177,12 +191,12 @@ BUG_REPORT_URL="https://bugs.debian.org/"
|
|||||||
let os_release: OsRelease = data.lines().map(str::to_owned).collect();
|
let os_release: OsRelease = data.lines().map(str::to_owned).collect();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(InitramfsType::Debian),
|
Some(InitramfsType::Debian),
|
||||||
detect_initramfs_type(&os_release)
|
detect_initramfs_type(&os_release).await
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn detect_initramfs_mint() {
|
async fn detect_initramfs_mint() {
|
||||||
let data = r#"
|
let data = r#"
|
||||||
NAME="Linux Mint"
|
NAME="Linux Mint"
|
||||||
VERSION="21.2 (Victoria)"
|
VERSION="21.2 (Victoria)"
|
||||||
@ -200,7 +214,7 @@ UBUNTU_CODENAME=jammy
|
|||||||
let os_release: OsRelease = data.lines().map(str::to_owned).collect();
|
let os_release: OsRelease = data.lines().map(str::to_owned).collect();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(InitramfsType::Debian),
|
Some(InitramfsType::Debian),
|
||||||
detect_initramfs_type(&os_release)
|
detect_initramfs_type(&os_release).await
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ mod info_row;
|
|||||||
mod page_section;
|
mod page_section;
|
||||||
mod root_stack;
|
mod root_stack;
|
||||||
|
|
||||||
use crate::{APP_ID, GUI_VERSION};
|
use crate::{create_connection, APP_ID, GUI_VERSION};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use apply_revealer::ApplyRevealer;
|
use apply_revealer::ApplyRevealer;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
@ -536,7 +536,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn enable_overclocking(&self) {
|
fn enable_overclocking(&self) {
|
||||||
let text = format!("This will enable the overdrive feature of the amdgpu driver by creating a file at <b>{MODULE_CONF_PATH}</b> and updating the initramfs. Are you sure you want to do this? (Note: the GUI may freeze for a bit)");
|
let text = format!("This will enable the overdrive feature of the amdgpu driver by creating a file at <b>{MODULE_CONF_PATH}</b> and updating the initramfs. Are you sure you want to do this?");
|
||||||
let dialog = MessageDialog::builder()
|
let dialog = MessageDialog::builder()
|
||||||
.title("Enable Overclocking")
|
.title("Enable Overclocking")
|
||||||
.use_markup(true)
|
.use_markup(true)
|
||||||
@ -548,7 +548,19 @@ impl App {
|
|||||||
|
|
||||||
dialog.run_async(clone!(@strong self as app => move |diag, response| {
|
dialog.run_async(clone!(@strong self as app => move |diag, response| {
|
||||||
if response == ResponseType::Ok {
|
if response == ResponseType::Ok {
|
||||||
match app.daemon_client.enable_overdrive().and_then(|buffer| buffer.inner()) {
|
let handle = gio::spawn_blocking(|| {
|
||||||
|
let (daemon_client, _) = create_connection().expect("Could not create new daemon connection");
|
||||||
|
daemon_client.enable_overdrive().and_then(|buffer| buffer.inner())
|
||||||
|
});
|
||||||
|
|
||||||
|
let dialog = app.spinner_dialog("Turning overclocking on (this may take a while)");
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
let result = handle.await.unwrap();
|
||||||
|
dialog.hide();
|
||||||
|
|
||||||
|
match result {
|
||||||
Ok(msg) => {
|
Ok(msg) => {
|
||||||
let success_dialog = MessageDialog::builder()
|
let success_dialog = MessageDialog::builder()
|
||||||
.title("Success")
|
.title("Success")
|
||||||
@ -564,6 +576,7 @@ impl App {
|
|||||||
show_error(&app.window, err);
|
show_error(&app.window, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
diag.hide();
|
diag.hide();
|
||||||
}));
|
}));
|
||||||
@ -573,7 +586,7 @@ impl App {
|
|||||||
let dialog = MessageDialog::builder()
|
let dialog = MessageDialog::builder()
|
||||||
.title("Disable Overclocking")
|
.title("Disable Overclocking")
|
||||||
.use_markup(true)
|
.use_markup(true)
|
||||||
.text("The overclocking functionality in the driver will now be turned off. (Note: the LACT window might hang)")
|
.text("The overclocking functionality in the driver will now be turned off.")
|
||||||
.message_type(MessageType::Info)
|
.message_type(MessageType::Info)
|
||||||
.buttons(ButtonsType::Ok)
|
.buttons(ButtonsType::Ok)
|
||||||
.transient_for(&self.window)
|
.transient_for(&self.window)
|
||||||
@ -581,7 +594,20 @@ impl App {
|
|||||||
|
|
||||||
dialog.run_async(clone!(@strong self as app => move |diag, _| {
|
dialog.run_async(clone!(@strong self as app => move |diag, _| {
|
||||||
diag.hide();
|
diag.hide();
|
||||||
match app.daemon_client.disable_overdrive().and_then(|buffer| buffer.inner()) {
|
|
||||||
|
let handle = gio::spawn_blocking(|| {
|
||||||
|
let (daemon_client, _) = create_connection().expect("Could not create new daemon connection");
|
||||||
|
daemon_client.disable_overdrive().and_then(|buffer| buffer.inner())
|
||||||
|
});
|
||||||
|
|
||||||
|
let dialog = app.spinner_dialog("Turning overclocking off (this may take a while)");
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
let result = handle.await.unwrap();
|
||||||
|
dialog.hide();
|
||||||
|
|
||||||
|
match result {
|
||||||
Ok(msg) => {
|
Ok(msg) => {
|
||||||
let success_dialog = MessageDialog::builder()
|
let success_dialog = MessageDialog::builder()
|
||||||
.title("Success")
|
.title("Success")
|
||||||
@ -597,6 +623,8 @@ impl App {
|
|||||||
show_error(&app.window, err);
|
show_error(&app.window, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,6 +678,25 @@ impl App {
|
|||||||
app.set_initial(&gpu_id);
|
app.set_initial(&gpu_id);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spinner_dialog(&self, title: &str) -> MessageDialog {
|
||||||
|
let spinner = gtk::Spinner::new();
|
||||||
|
spinner.start();
|
||||||
|
spinner.set_margin_top(10);
|
||||||
|
spinner.set_margin_bottom(10);
|
||||||
|
|
||||||
|
let dialog = MessageDialog::builder()
|
||||||
|
.title(title)
|
||||||
|
.child(&spinner)
|
||||||
|
.message_type(MessageType::Info)
|
||||||
|
.transient_for(&self.window)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
dialog.titlebar().unwrap().set_margin_start(15);
|
||||||
|
dialog.titlebar().unwrap().set_margin_end(15);
|
||||||
|
|
||||||
|
dialog
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_error(parent: &ApplicationWindow, err: anyhow::Error) {
|
fn show_error(parent: &ApplicationWindow, err: anyhow::Error) {
|
||||||
|
@ -4,7 +4,7 @@ use anyhow::{anyhow, Context};
|
|||||||
use app::App;
|
use app::App;
|
||||||
use lact_client::{schema::args::GuiArgs, DaemonClient};
|
use lact_client::{schema::args::GuiArgs, DaemonClient};
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use tracing::{error, info, metadata::LevelFilter};
|
use tracing::{debug, error, info, metadata::LevelFilter};
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
const GUI_VERSION: &str = env!("CARGO_PKG_VERSION");
|
const GUI_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
@ -29,7 +29,10 @@ pub fn run(args: GuiArgs) -> anyhow::Result<()> {
|
|||||||
|
|
||||||
fn create_connection() -> anyhow::Result<(DaemonClient, Option<anyhow::Error>)> {
|
fn create_connection() -> anyhow::Result<(DaemonClient, Option<anyhow::Error>)> {
|
||||||
match DaemonClient::connect() {
|
match DaemonClient::connect() {
|
||||||
Ok(connection) => Ok((connection, None)),
|
Ok(connection) => {
|
||||||
|
debug!("Established daemon connection");
|
||||||
|
Ok((connection, None))
|
||||||
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
info!("could not connect to socket: {err:#}");
|
info!("could not connect to socket: {err:#}");
|
||||||
info!("using a local daemon");
|
info!("using a local daemon");
|
||||||
|
Loading…
Reference in New Issue
Block a user