最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c - Catching signal with a destination - Stack Overflow

programmeradmin4浏览0评论

I have a dbus (linux) program in C that send a signal with a destination. The code is the following:

#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus.h>
#include <unistd.h>

/**
 * Connect to the DBUS bus and send a broadcast signal
 */
void sendsignal(DBusConnection* conn, char* sigvalue)
{
   DBusMessage* msg;
   DBusMessageIter args;
   DBusError err;
   int ret;
   dbus_uint32_t serial = 0;

   printf("Sending signal with value %s\n", sigvalue);

   // create a signal & check for errors 
   msg = dbus_message_new_signal("/test/signal/Object", // object name of the signal
                                 "test.signal.Type", // interface name of the signal
                                 "Test"); // name of the signal
   if (NULL == msg) 
   { 
      fprintf(stderr, "Message Null\n"); 
      exit(1); 
   }

   // set the destination of the signal
   dbus_message_set_destination(msg, "it.smartsecurity.dbus");


   // append arguments onto signal
   dbus_message_iter_init_append(msg, &args);
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }

   // send the message and flush the connection
   if (!dbus_connection_send(conn, msg, &serial)) {
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }

   dbus_connection_flush(conn);
   
   printf("Signal Sent\n");
   
   // free the message and close the connection
   dbus_message_unref(msg);
   //dbus_connection_close(conn);
}


int main(int argc, char **argv) {

   DBusMessage* msg;
   DBusMessageIter args;
   DBusConnection* conn;
   DBusError err; 
   int ret;

   // initialise the error value
   dbus_error_init(&err);

   // connect to the DBUS system bus, and check for errors
   conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Connection Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (NULL == conn) { 
      exit(1); 
   }

   // register our name on the bus, and check for errors
   ret = dbus_bus_request_name(conn, "it.smartsecurity.dbus", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Name Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 
      exit(1);
   }

   do {
      
      sendsignal(conn, "CIAO");
      sleep(1);
      
   } while (1);

   // dbus_connection_close(conn);
   return 0;
}

Then with zbus crate I wrote the followng code:

use futures_util::stream::StreamExt;
use zbus::{zvariant::OwnedObjectPath, proxy, Connection};
use zbus::zvariant::Value;


#[proxy(
    default_service = "it.smartsecurity.dbus",
    default_path = "/test/signal/Object",
    interface = "test.signal.Type",
)]
trait Systemd1Manager {
    // Defines signature for D-Bus signal named `Test`
    #[zbus(signal)]
    fn test(&self, unit: String) -> zbus::Result<()>; // si deve chiamare come il segnale
}

async fn watch_systemd_jobs() -> zbus::Result<()> {
    let connection = Connection::system().await?;
    // `Systemd1ManagerProxy` is generated from `Systemd1Manager` trait
  
    let systemd_proxy = Systemd1ManagerProxy::builder(&connection)
        .destination("it.smartsecurity.dbus")?
        .path("/test/signal/Object")?
        .interface("test.signal.Type")?
        .build().await?;

    // Method `receive_job_new` is generated from `job_new` signal
    let mut new_jobs_stream = systemd_proxy.receive_test().await?;

    while let Some(msg) = new_jobs_stream.next().await {
        //dbg!(&msg);
        // struct `JobNewArgs` is generated from `job_new` signal function arguments
        let args = msg.args();
        dbg!(&args);

        println!("=====================");
        // stampa il nome del servizio e il suo valore
        let x = msg.message().header();
        
        let y = x.member();
        if y.is_some() {
            println!("Header: {}", y.unwrap());
        }

        dbg!(&y);

        let unit = args.unwrap().unit;
        println!("Param: {}", unit);

    }

    panic!("Stream ended unexpectedly");
}

#[tokio::main]
async fn main() {
    watch_systemd_jobs().await.unwrap();
}

My problem is that this Rust code doesn't catch the signal and I don't understand what I'm doing wrong.

I have a dbus (linux) program in C that send a signal with a destination. The code is the following:

#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus.h>
#include <unistd.h>

/**
 * Connect to the DBUS bus and send a broadcast signal
 */
void sendsignal(DBusConnection* conn, char* sigvalue)
{
   DBusMessage* msg;
   DBusMessageIter args;
   DBusError err;
   int ret;
   dbus_uint32_t serial = 0;

   printf("Sending signal with value %s\n", sigvalue);

   // create a signal & check for errors 
   msg = dbus_message_new_signal("/test/signal/Object", // object name of the signal
                                 "test.signal.Type", // interface name of the signal
                                 "Test"); // name of the signal
   if (NULL == msg) 
   { 
      fprintf(stderr, "Message Null\n"); 
      exit(1); 
   }

   // set the destination of the signal
   dbus_message_set_destination(msg, "it.smartsecurity.dbus");


   // append arguments onto signal
   dbus_message_iter_init_append(msg, &args);
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }

   // send the message and flush the connection
   if (!dbus_connection_send(conn, msg, &serial)) {
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }

   dbus_connection_flush(conn);
   
   printf("Signal Sent\n");
   
   // free the message and close the connection
   dbus_message_unref(msg);
   //dbus_connection_close(conn);
}


int main(int argc, char **argv) {

   DBusMessage* msg;
   DBusMessageIter args;
   DBusConnection* conn;
   DBusError err; 
   int ret;

   // initialise the error value
   dbus_error_init(&err);

   // connect to the DBUS system bus, and check for errors
   conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Connection Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (NULL == conn) { 
      exit(1); 
   }

   // register our name on the bus, and check for errors
   ret = dbus_bus_request_name(conn, "it.smartsecurity.dbus", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Name Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 
      exit(1);
   }

   do {
      
      sendsignal(conn, "CIAO");
      sleep(1);
      
   } while (1);

   // dbus_connection_close(conn);
   return 0;
}

Then with zbus crate I wrote the followng code:

use futures_util::stream::StreamExt;
use zbus::{zvariant::OwnedObjectPath, proxy, Connection};
use zbus::zvariant::Value;


#[proxy(
    default_service = "it.smartsecurity.dbus",
    default_path = "/test/signal/Object",
    interface = "test.signal.Type",
)]
trait Systemd1Manager {
    // Defines signature for D-Bus signal named `Test`
    #[zbus(signal)]
    fn test(&self, unit: String) -> zbus::Result<()>; // si deve chiamare come il segnale
}

async fn watch_systemd_jobs() -> zbus::Result<()> {
    let connection = Connection::system().await?;
    // `Systemd1ManagerProxy` is generated from `Systemd1Manager` trait
  
    let systemd_proxy = Systemd1ManagerProxy::builder(&connection)
        .destination("it.smartsecurity.dbus")?
        .path("/test/signal/Object")?
        .interface("test.signal.Type")?
        .build().await?;

    // Method `receive_job_new` is generated from `job_new` signal
    let mut new_jobs_stream = systemd_proxy.receive_test().await?;

    while let Some(msg) = new_jobs_stream.next().await {
        //dbg!(&msg);
        // struct `JobNewArgs` is generated from `job_new` signal function arguments
        let args = msg.args();
        dbg!(&args);

        println!("=====================");
        // stampa il nome del servizio e il suo valore
        let x = msg.message().header();
        
        let y = x.member();
        if y.is_some() {
            println!("Header: {}", y.unwrap());
        }

        dbg!(&y);

        let unit = args.unwrap().unit;
        println!("Param: {}", unit);

    }

    panic!("Stream ended unexpectedly");
}

#[tokio::main]
async fn main() {
    watch_systemd_jobs().await.unwrap();
}

My problem is that this Rust code doesn't catch the signal and I don't understand what I'm doing wrong.

Share Improve this question edited Feb 17 at 9:03 cafce25 27.5k5 gold badges44 silver badges55 bronze badges asked Feb 17 at 7:37 ChrisChris 4591 gold badge5 silver badges16 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 6

When you send bus messages to a specific destination, then they are no longer broadcast (contrary to your code comments) – they are only delivered to that destination. Only the process which has claimed the bus name it.smartsecurity.dbus will be able to receive such signals.

In your code, the bus name is claimed by the sender rather than the receiver, and therefore the sender is actually sending the signals to itself.

发布评论

评论列表(0)

  1. 暂无评论