/*
* Copyright (c) 2012 Novell, Inc.
- * Copyright (c) 2023 SUSE LLC
+ * Copyright (c) [2023-2026] SUSE LLC
*
* All Rights Reserved.
*
if (!conn)
{
- SN_THROW(FatalException());
+ SN_THROW(FatalException("dbus_bus_get() returned null"));
}
+
+ dbus_connection_set_exit_on_disconnect(conn, false);
}
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
- SN_THROW(FatalException());
+ SN_THROW(FatalException("dbus_bus_request_name() failed"));
}
}
if (!dbus_connection_send(conn, m.get_message(), NULL))
{
- SN_THROW(FatalException());
+ SN_THROW(FatalException("dbus_connection_send() failed"));
}
}
if (dbus_error_is_set(&err))
{
dbus_error_free(&err);
- SN_THROW(FatalException());
+ SN_THROW(FatalException("dbus_bus_add_match() failed"));
}
}
if (dbus_error_is_set(&err))
{
dbus_error_free(&err);
- SN_THROW(FatalException());
+ SN_THROW(FatalException("dbus_bus_remove_match() failed"));
}
}
{
boost::lock_guard<boost::mutex> lock(mutex);
- return dbus_connection_pop_message(conn);
+ DBusMessage* msg = dbus_connection_pop_message(conn);
+
+ // Being disconnected by dbus can be simulated with something like "strace -e
+ // fault=recvmsg:error=ECONNRESET:when=10+ /usr/sbin/snapperd --logger-type
+ // stdout".
+
+ if (msg &&
+ strcmp(dbus_message_get_interface(msg), DBUS_INTERFACE_LOCAL) == 0 &&
+ strcmp(dbus_message_get_member(msg), "Disconnected") == 0)
+ {
+ throw FatalException("disconnected from dbus");
+ }
+
+ return msg;
}
const string sender = m.get_sender();
if (sender.empty())
{
- SN_THROW(FatalException());
+ SN_THROW(FatalException("get_sender() returned empty sender"));
}
DBusError err;
+-------------------------------------------------------------------
+Thu Jun 11 10:21:28 CEST 2026 - Arvin Schnell <aschnell@suse.com>
+
+- improved error handling when disconnected by dbus (see
+ gh#openSUSE/snapper#223)
+
-------------------------------------------------------------------
Wed Jun 10 09:13:13 CEST 2026 - Arvin Schnell <aschnell@suse.com>
signal(SIGPIPE, SIG_IGN);
- dbus_threads_init_default();
+ try
+ {
+ dbus_threads_init_default();
- MyMainLoop mainloop(DBUS_BUS_SYSTEM);
+ MyMainLoop mainloop(DBUS_BUS_SYSTEM);
- mainloop.set_idle_timeout(idle_time);
+ mainloop.set_idle_timeout(idle_time);
- y2mil("Requesting DBus name");
+ y2mil("Requesting DBus name");
- try
- {
mainloop.request_name(SERVICE, DBUS_NAME_FLAG_REPLACE_EXISTING);
- }
- catch (const Exception& e)
- {
- SN_CAUGHT(e);
- y2err("Failed to request DBus name");
+ y2mil("Loading snapper configs");
- return EXIT_FAILURE;
- }
+ try
+ {
+ meta_snappers.init();
+ }
+ catch (const Exception& e)
+ {
+ SN_CAUGHT(e);
- y2mil("Loading snapper configs");
+ y2err("Failed to load snapper configs");
- try
- {
- meta_snappers.init();
+ return EXIT_FAILURE;
+ }
+
+ y2mil("Listening for method calls and signals");
+
+ mainloop.run();
+
+ y2mil("Exiting");
+
+ meta_snappers.unload();
}
catch (const Exception& e)
{
SN_CAUGHT(e);
- y2err("Failed to load snapper configs");
+ return EXIT_FAILURE;
}
- y2mil("Listening for method calls and signals");
-
- mainloop.run();
-
- y2mil("Exiting");
-
- meta_snappers.unload();
-
return EXIT_SUCCESS;
}