【问题标题】:How to detect application uniqueness in Rust using dbus如何使用 dbus 检测 Rust 中的应用程序唯一性
【发布时间】:2019-09-26 10:46:14
【问题描述】:

如何在 Rust 中使用 dbus crate(https://crates.io/crates/dbus) 检测应用程序的唯一性?

到目前为止,我已经尝试了以下方法,但该函数始终返回 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)
        },
    }
}

我不确定these 中的哪一个暗示了应用程序的唯一性。

如果函数到达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);
}

导致程序认为它总是独一无二的。

【问题讨论】:

  • 可能值得重新安排函数以提供更多的布尔值。调用request_name()的具体输出是什么?
  • @E_net4theMeta-RemoveR,改为pastebin.com/XLepk1jT表示到达RequestNameReply::PrimaryOwner。我不确定其中哪一个 (docs.rs/dbus/0.7.1/dbus/blocking/stdintf/org_freedesktop_dbus/…) 最能体现应用程序的独特性。
  • 我没有使用过 Rust 的 D-Bus,但看看你的代码,我猜会发生这种情况:你总是成为名称所有者,然后 Session/Connection 立即超出范围,导致名义发布。

标签: rust dbus


【解决方案1】:

dbus::blocking::Connection 超出范围时,它将被删除,并导致the underlying dbus connection 也被删除。

为了对连接做任何有意义的事情,你需要让它保持活跃。一种方法是创建一次连接并传递引用:

//# 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),
    }
}

尝试运行程序两次,第二个实例将立即终止。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2017-05-17
    • 2011-04-13
    • 2014-04-29
    • 1970-01-01
    相关资源
    最近更新 更多