Как определить уникальность приложения в Rust с помощью dbus - PullRequest
3 голосов
/ 26 сентября 2019

Как я могу определить уникальность приложения, используя dbus crate (https://crates.io/crates/dbus) в Rust?

До сих пор я пробовал следующее, но функция всегда возвращает false.

pub fn detect_uniqueness() -> Result<bool, Box<dyn std::error::Error>> {
    let conn = dbus::blocking::Connection::new_session()?;
    match conn.request_name("com.localserver.myapp", false, false, false) {
        Err(e) => Err(Box::new(e)),
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::Exists) => Ok(true),
        _ => Ok(false)
    }
}

Изменение функции на следующее указывает, что функция всегда достигает RequestReply::PrimaryOwner.

pub fn detect_uniqueness() -> Result<bool, Box<dyn std::error::Error>> {
    let conn = dbus::blocking::Connection::new_session()?;
    match conn.request_name("com.localserver.myapp", false, false, false) {
        Err(e) => Err(Box::new(e)),
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::PrimaryOwner) => {
            log::info!("PrimaryOwner");
            Ok(true)
        },
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::InQueue) => {
            log::info!("InQueue");
            Ok(false)
        },
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::Exists) => {
            log::info!("Exists");
            Ok(false)
        },
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::AlreadyOwner) => {
            log::info!("AlreadyOwner");
            Ok(false)
        },
    }
}

Я не уверен, какой из этих подразумевает уникальность приложения.

Я пытался удержать первый экземпляр программы, если функция достигает PrimaryOwner, и запустить другой экземпляр, но, кажется, даже второй экземпляр тоже достигает PrimaryOwner.

// main.rs
fn main() {
    aux::logger::init();

    if app::manually_invoked() {
        match app::unique_instance() {
            Ok(unique) => {
                if unique {
                    log::info!("Unique instance detected.");
                    loop {
                        std::thread::sleep_ms(999999);
                    }
                } else {
                    log::info!("Duplicate instance detected.")
                }
            },
            Err(e) => {
                log::error!("Error detecting uniqueness: {}.", e);
                app::exit();
            }
        }
    } else {
        // 
    }
}
// app.rs
pub fn manually_invoked() -> bool {
    std::env::args().len() == 1
}

pub fn unique_instance() -> Result<bool, Box<dyn std::error::Error>> {
    crate::aux::ipc::detect_uniqueness()
}

pub fn exit() {
    std::process::exit(1);
}

В результате программа думает, что она всегда уникальна.

1 Ответ

1 голос
/ 26 сентября 2019

Когда dbus::blocking::Connection выходит из области видимости, оно будет отброшено, и в результате будет также удалено базовое dbus соединение .

Чтобы сделать что-либо значимое ссвязи, вы должны поддерживать это.Один из способов сделать это - создать соединение один раз и передать ссылку:

//# dbus = "0.7.1"

use dbus;
use dbus::blocking::Connection;
use dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let conn = Connection::new_session()?;
    match is_unique(&conn) {
        Ok(true) => loop {},
        _ => Ok(()),
    }
}

pub fn is_unique(conn: &Connection) -> Result<bool, dbus::Error> {
    match conn.request_name("com.localserver.myapp", false, false, false) {
        Ok(RequestNameReply::PrimaryOwner) => Ok(true),
        Ok(_) => Ok(false),
        Err(e) => Err(e),
    }
}

Попробуйте запустить программу дважды, и второй экземпляр немедленно прекратит работу.

...