skip to Main Content

I’m using RHEL 8 and systemd version is 239-74
I want to get data using dbus on c++
It’s not a problem when using just one container(but this case also occur same error when exiting container)
But when i should use one more containers I get "Device or Resource busy"

#include <iostream>
#include <unistd.h>
#include <systemd/sd-bus.h>

int main() {
        sd_bus_error error = SD_BUS_ERROR_NULL;
        sd_bus *bus = nullptr;
        int ret = sd_bus_open_system(&bus);
        const char *service_name = "org.freedesktop.systemd1";
        const char *object_path = "/org/freedesktop/systemd1";
        const char *interface = "org.freedesktop.systemd1.Manager";
        const char *method = "ListUnits";

        sd_bus_message *reply = nullptr;
        ret = sd_bus_call_method(bus,
                        service_name,
                        object_path,
                        interface,
                        method,
                        &error,
                        &reply,
                        "");
        if (ret < 0) {
                return 1;
        }
        const char *unit_name;
        const char *unit_description;
        const char *unit_load_state;
        const char *unit_active_state;
        const char *sub_state,*followed_state,*object1_path,*queued_job,*job_type,*job_object_path;
        unsigned int uint;

        ret = sd_bus_message_enter_container(reply, 'a', "(ssssssouso)");
        if(ret<0){
                std::cerr <<strerror(-ret);
        }
        ret = sd_bus_message_exit_container(reply);
        if(ret<0){
                std::cerr <<strerror(-ret);
        }
        sd_bus_message_unref(reply);
        sd_bus_unref(bus);

        return 0;
}

I think environment problem but on Ubuntu, same error occurred.
I want read array of dict, but i can’t exit container so i can’t get other data

2

Answers


  1. Chosen as BEST ANSWER

    Then, When using GetAll method in DBus.properties, the result is

    "   array [
      dict entry(
         string "Id"
         variant             string "cockpit.service"
      )
      dict entry(
         string "Names"
         variant             array [
               string "cockpit.service"
            ]
      )
      dict entry(
         string "Following"
         variant             string ""
      )
      dict entry(
         string "Requires"
         variant             array [
               string "sysinit.target"
               string "system.slice"
               string "cockpit-wsinstance-http.socket"
               string "cockpit-wsinstance-https-factory.socket"
               string "cockpit-wsinstance-http-redirect.socket"
               string "-.mount"
               string "cockpit.socket"
            ]
      )
    

    .... ]

    So, I entered first array container using sd_bus_message_enter_container(reply,'a',"{sv}") And entered second sv container using (reply,'e',"sv"). Then, I want read data from this container but their data types are different. So i can't read data like , read(reply,"s",&data) (const char * data) because it can be string, array, array of bytes .... So, how do i get this data?


  2. From the documentation:

    Note that sd_bus_message_exit_container() may only be called after iterating through all members of the container, i.e. reading or skipping over them.

    You need to consume the contents of the array before exiting the container:

    ret = sd_bus_message_enter_container(reply, 'a', "(ssssssouso)");
    if(ret<0){
        std::cerr <<strerror(-ret);
    }
    
    struct {
        const char *primary_name, *human_name, *load_state, *active_state, *sub_state, *following;
        const char **unit_object_path;
        uint32_t queued_job_id;
        const char *job_type
        const char **job_object_path;
    } unit;
    
    for (;;) {
        ret = sd_bus_message_read(reply, "(ssssssouso)", &unit.primary_name, &unit.human_name, &unit.load_state, &unit.active_state, &unit.sub_state, &unit.following, &unit.unit_object_path, &unit.queued_job_id, &unit.job_type, &unit.job_object_path);
        if (ret == 0) {
            // done reading
            break;
        }
        if(ret<0){
            std::cerr <<strerror(-ret);
            break;
        }
    }
    
    ret = sd_bus_message_exit_container(reply);
    if(ret<0){
        std::cerr <<strerror(-ret);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search