使用 gdbus-codegen 连接到 systemd DBUS 信号
Connecting to systemd DBUS signals using gdbus-codegen
使用 gdbus-codegen 生成的管理器代理时,我无法接收 systemd DBus 信号。但是我能够通过 DBus 成功调用 systemd 提供的方法。
我在网上搜索并查看了这些链接,但没有成功。当 gdbus-codegen 用于 systemd API.
时,没有太多关于如何做到这一点的例子
- https://developer.gnome.org/gio/stable/gdbus-codegen.html
- http://www.freedesktop.org/software/gstreamer-sdk/data/docs/latest/gio/ch30s05.html
这是我对代码片段所做的。
1) 我生成了 systemd 自省并将其 XML 作为 gdbus-codegen 的输入。
...剪断
<interface name="org.freedesktop.systemd1.Manager">
<signal name="JobRemoved">
<arg type="u"/> <arg type="o"/> <arg type="s"/> <arg type="s"/>
</signal>
...剪断
2) 编写我的客户端代码以使用由 gdbus-codegen 生成的 C APIs 并创建一个管理器代理。 (一切都在系统总线上)。
SystemdManager *systemdProxy = systemd_manager_proxy_new_for_bus_sync(
G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
"org.freedesktop.systemd1", "/org/freedesktop/systemd1",
NULL, error);
3) 定义信号处理程序
static void on_done(GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
LOG_ERROR("on_done");
}
4) 将信号处理程序连接到 JobRemoved 信号的代理。
if (g_signal_connect(systemdProxy, "job-removed",
G_CALLBACK(on_done), NULL) <= 0 )
{
LOG_ERROR("Failed to connect to signal job-removed");
}
5) 使用代理启动 systemd 服务。 returns 成功,我可以看到单元开始,运行 一两秒然后终止。
ret = systemd_manager_call_start_unit_sync(
systemdProxy, unit_name, unit_mode, &job_obj,
NULL, &error);
6) systemd 生成一个 JobRemoved 信号。 dbus-monitor 显示它。
signal sender=:1.0 -> dest=(null destination) serial=11931
path=/org/freedesktop/systemd1;
interface=org.freedesktop.systemd1.Manager;
member=JobRemoved
uint32 7009
object path "/org/freedesktop/systemd1/job/7009"
string "mysample.service"
string "done"
7) 我的信号处理程序从未被调用过。 (一切都使用系统总线,没有其他总线)。我为 detailed_signal
尝试了各种字符串 g_signal_connect
的第二个参数(例如:JobRemoved
、job_removed
、::job-removed
,有些不被 g_signal_connect
接受).
非常感谢任何帮助!
解决方案是在我的程序中使用 glib event loop
。我的程序没有 运行 GMainLoop
从 glib
获得任何回调所必需的。这不是一种优雅的方式,但出于各种原因,我决定生成一个新线程,该线程将在 g_main_loop_run 上阻塞。这是它的样子。
void *event_loop_thread(void *unused) {
GMainLoop *loop = g_main_loop_new(NULL, 0);
g_main_loop_run(loop);
}
int main() {
// snip
pthread_create(&thread_id, NULL, event_loop_thread, NULL);
// do steps 2 to 6, and at step 7 signal handler is called
}
此外,我还必须修复我的信号处理程序签名,使其与接收有意义参数的信号兼容。
static void on_done(SystemdManager *manager,
guint32 job_id,
gchar *job_obj,
gchar *unit_name,
gchar *status)
{
LOG_ERROR("on_done");
}
使用 gdbus-codegen 生成的管理器代理时,我无法接收 systemd DBus 信号。但是我能够通过 DBus 成功调用 systemd 提供的方法。
我在网上搜索并查看了这些链接,但没有成功。当 gdbus-codegen 用于 systemd API.
时,没有太多关于如何做到这一点的例子- https://developer.gnome.org/gio/stable/gdbus-codegen.html
- http://www.freedesktop.org/software/gstreamer-sdk/data/docs/latest/gio/ch30s05.html
这是我对代码片段所做的。
1) 我生成了 systemd 自省并将其 XML 作为 gdbus-codegen 的输入。
...剪断
<interface name="org.freedesktop.systemd1.Manager">
<signal name="JobRemoved">
<arg type="u"/> <arg type="o"/> <arg type="s"/> <arg type="s"/>
</signal>
...剪断
2) 编写我的客户端代码以使用由 gdbus-codegen 生成的 C APIs 并创建一个管理器代理。 (一切都在系统总线上)。
SystemdManager *systemdProxy = systemd_manager_proxy_new_for_bus_sync(
G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
"org.freedesktop.systemd1", "/org/freedesktop/systemd1",
NULL, error);
3) 定义信号处理程序
static void on_done(GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
LOG_ERROR("on_done");
}
4) 将信号处理程序连接到 JobRemoved 信号的代理。
if (g_signal_connect(systemdProxy, "job-removed",
G_CALLBACK(on_done), NULL) <= 0 )
{
LOG_ERROR("Failed to connect to signal job-removed");
}
5) 使用代理启动 systemd 服务。 returns 成功,我可以看到单元开始,运行 一两秒然后终止。
ret = systemd_manager_call_start_unit_sync(
systemdProxy, unit_name, unit_mode, &job_obj,
NULL, &error);
6) systemd 生成一个 JobRemoved 信号。 dbus-monitor 显示它。
signal sender=:1.0 -> dest=(null destination) serial=11931
path=/org/freedesktop/systemd1;
interface=org.freedesktop.systemd1.Manager;
member=JobRemoved
uint32 7009
object path "/org/freedesktop/systemd1/job/7009"
string "mysample.service"
string "done"
7) 我的信号处理程序从未被调用过。 (一切都使用系统总线,没有其他总线)。我为 detailed_signal
尝试了各种字符串 g_signal_connect
的第二个参数(例如:JobRemoved
、job_removed
、::job-removed
,有些不被 g_signal_connect
接受).
非常感谢任何帮助!
解决方案是在我的程序中使用 glib event loop
。我的程序没有 运行 GMainLoop
从 glib
获得任何回调所必需的。这不是一种优雅的方式,但出于各种原因,我决定生成一个新线程,该线程将在 g_main_loop_run 上阻塞。这是它的样子。
void *event_loop_thread(void *unused) {
GMainLoop *loop = g_main_loop_new(NULL, 0);
g_main_loop_run(loop);
}
int main() {
// snip
pthread_create(&thread_id, NULL, event_loop_thread, NULL);
// do steps 2 to 6, and at step 7 signal handler is called
}
此外,我还必须修复我的信号处理程序签名,使其与接收有意义参数的信号兼容。
static void on_done(SystemdManager *manager,
guint32 job_id,
gchar *job_obj,
gchar *unit_name,
gchar *status)
{
LOG_ERROR("on_done");
}