Commit bae87438 authored by spiiroin's avatar spiiroin

[systemd] Use cached SystemBus connection. Fixes MER#1694

Usb-moded opens and closes a private peer-to-peer dbus connection for each
systemd unit start/stop it needs to perform. This is relatively heavy
operation and seems to cause problems with systemd v225 during bootup.

Since usb-moded no longer has any reason to communicate with systemd
before it can connect to SystemBus, we can drop the private connections
and use cached SystemBus connection instead.
Signed-off-by: spiiroin's avatarSimo Piiroinen <simo.piiroinen@jollamobile.com>
parent 40463c7a
......@@ -35,69 +35,129 @@
#include "usb_moded-log.h"
#include "usb_moded-systemd.h"
static DBusConnection * get_systemd_dbus_connection(void)
{
DBusError error;
DBusConnection *conn = 0;
dbus_error_init(&error);
conn = dbus_connection_open_private("unix:path=/run/systemd/private", &error);
if (!conn)
{
if (dbus_error_is_set(&error))
log_err("Cannot connect to systemd: %s", error.message);
else
log_err("Cannot connect to systemd");
dbus_error_free(&error);
return 0;
}
return conn;
}
#define SYSTEMD_DBUS_SERVICE "org.freedesktop.systemd1"
#define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1"
#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.systemd1.Manager"
/* SystemBus connection ref used for systemd control ipc */
static DBusConnection *systemd_con = NULL;
// QDBusObjectPath org.freedesktop.systemd1.Manager.StartUnit(QString name, QString mode)
// QDBusObjectPath org.freedesktop.systemd1.Manager.StopUnit(QString name, QString mode)
// mode = replace
// method = StartUnit or StopUnit
gboolean systemd_control_service(const char *name, const char *method)
{
DBusMessage *req = NULL;
DBusMessage *rsp = NULL;
DBusError err = DBUS_ERROR_INIT;
const char *arg = "replace";
const char *res = 0;
log_debug("%s(%s) ...", method, name);
if( !systemd_con ) {
log_err("not connected to system bus; skip systemd unit control");
goto EXIT;
}
req = dbus_message_new_method_call(SYSTEMD_DBUS_SERVICE,
SYSTEMD_DBUS_PATH,
SYSTEMD_DBUS_INTERFACE,
method);
if( !req ) {
log_err("failed to construct %s.%s request",
SYSTEMD_DBUS_INTERFACE,
method);
goto EXIT;
}
if( !dbus_message_append_args(req,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &arg,
DBUS_TYPE_INVALID))
{
log_debug("error appending arguments");
goto EXIT;
}
rsp = dbus_connection_send_with_reply_and_block(systemd_con, req, -1, &err);
if( !rsp ) {
log_err("no reply to %s.%s request: %s: %s",
SYSTEMD_DBUS_INTERFACE,
method,
err.name, err.message);
goto EXIT;
}
if( dbus_set_error_from_message(&err, rsp) ) {
log_err("got error reply to %s.%s request: %s: %s",
SYSTEMD_DBUS_INTERFACE,
method,
err.name, err.message);
goto EXIT;
}
if( !dbus_message_get_args(rsp, &err,
DBUS_TYPE_OBJECT_PATH, &res,
DBUS_TYPE_INVALID) ) {
log_err("failed to parse reply to %s.%s request: %s: %s",
SYSTEMD_DBUS_INTERFACE,
method,
err.name, err.message);
goto EXIT;
}
EXIT:
dbus_error_free(&err);
if( rsp ) dbus_message_unref(rsp);
if( req ) dbus_message_unref(req);
log_debug("%s(%s) -> %s", method, name, res ?: "N/A");
return res != 0;
}
/* ========================================================================= *
* start/stop systemd control availability
* ========================================================================= */
gboolean
systemd_control_start(void)
{
gboolean ack = FALSE;
log_debug("starting systemd control");
/* Get connection ref */
if( (systemd_con = usb_moded_dbus_get_connection()) == 0 )
{
log_err("Could not connect to dbus for systemd control\n");
goto cleanup;
}
ack = TRUE;
DBusConnection *bus;
DBusError error;
DBusMessage *msg = NULL, *reply = NULL;
gboolean ret = FALSE;
const char * replace = "replace";
dbus_error_init(&error);
log_debug("Handling %s, with systemd, method %s\n", name, method);
bus = get_systemd_dbus_connection();
if(!bus)
return(ret);
msg = dbus_message_new_method_call("org.freedesktop.systemd1",
"/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", method);
if(msg)
{
if(!dbus_message_append_args (msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &replace, DBUS_TYPE_INVALID))
{
log_debug("error appending arguments\n");
dbus_message_unref(msg);
goto quit;
}
reply = dbus_connection_send_with_reply_and_block(bus, msg, -1, &error);
if(reply)
{
dbus_message_unref(reply);
ret = TRUE;
}
dbus_message_unref(msg);
}
quit:
dbus_connection_close(bus);
dbus_connection_unref(bus);
dbus_error_free(&error);
return(ret);
cleanup:
return ack;
}
void
systemd_control_stop(void)
{
log_debug("stopping systemd control");
if(systemd_con)
{
/* Let go of connection ref */
dbus_connection_unref(systemd_con),
systemd_con = 0;
}
}
......@@ -24,3 +24,5 @@
#define SYSTEMD_START "StartUnit"
gboolean systemd_control_service(const char *name, const char *method);
gboolean systemd_control_start(void);
void systemd_control_stop(void);
......@@ -54,6 +54,7 @@
#include "usb_moded-network.h"
#include "usb_moded-mac.h"
#include "usb_moded-android.h"
#include "usb_moded-systemd.h"
#ifdef MEEGOLOCK
#include "usb_moded-dsme.h"
#endif
......@@ -1197,6 +1198,11 @@ int main(int argc, char* argv[])
goto EXIT;
}
if( !systemd_control_start() ) {
log_crit("systemd control could not be started");
goto EXIT;
}
/* init daemon into a clean state first, then dbus and hw_abstraction last */
usb_moded_init();
......@@ -1252,6 +1258,7 @@ int main(int argc, char* argv[])
EXIT:
dsme_listener_stop();
handle_exit();
systemd_control_stop();
allow_suspend();
return result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment