Merge lp:~pitti/indicator-session/libupower-glib into lp:indicator-session/0.1

Proposed by Martin Pitt
Status: Rejected
Rejected by: Ted Gould
Proposed branch: lp:~pitti/indicator-session/libupower-glib
Merge into: lp:indicator-session/0.1
Diff against target: 261 lines (+39/-138)
2 files modified
configure.ac (+3/-1)
src/session-service.c (+36/-137)
To merge this branch: bzr merge lp:~pitti/indicator-session/libupower-glib
Reviewer Review Type Date Requested Status
Martin Pitt Needs Resubmitting
Ted Gould (community) Needs Information
David Barth Needs Information
Review via email: mp+19392@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

DeviceKit-power, and now upower provide a very convenient client-side library, which also respects per-user PolicyKit privileges (see bug 432598).

This branch provides the port from DeviceKit-power D-Bus to libupower-glib.

I'd like to upload this into lucid really soon, to get it into alpha-3. Can you please merge this and do a new upstream release?

Thanks!

Revision history for this message
David Barth (dbarth) wrote :

The simplification of the code + relying on a specialized library seems better. Any disadvantages or compatibility issues with using /only/ libupower?

review: Needs Information
Revision history for this message
Martin Pitt (pitti) wrote :

Well, the client-side library (libdevkit-power-gobject, and now libupower-glib) is _the_ official API for upower, which is also being used by gnome-power-manager, gnome-session, etc. So this is more stable than the upower D-Bus API (even now you can still use libdevkit-power-gobject and it will transparently use upower).

The obvious disadvantage that this patch brings is that it now introduces a dependency on a new library. I don't personally see a problem with it, but if you want to support upstream releases which build without dk-power/upower, I'm happy to add some configure autodetection and just disable the suspend/hibernate bits if libupower-glib is not available.

Revision history for this message
David Barth (dbarth) wrote :

Martin Pitt wrote:
> The obvious disadvantage that this patch brings is that it now introduces a dependency on a new library. I don't personally see a problem with it, but if you want to support upstream releases which build without dk-power/upower, I'm happy to add some configure autodetection and just disable the suspend/hibernate bits if libupower-glib is not available.
>
I think that's fine. Adding that compatibility option can be restored
later, whereas getting user testing should be as soon as possible.

I'll let Ted comment, but would support the patch as is.

Thanks

David

Revision history for this message
Ted Gould (ted) wrote :

There are a few issues with the patch.

It uses the _sync calls, but we have a requirement to make all DBus
operations async in the various indicator code. I'm unclear whether
up_client_get_can_suspend is sync or async.

I generally prefer to check for all the libraries at once in
configure.ac. I find that this frustrates users less as they get all
the errors at once instead of getting one error, the next error, as they
go through the configure script.

It should really use g_strcmp0 instead of strcmp as it protects from
NULL strings which will otherwise be crashers.

It seems that the screensaver_unthrottle() was removed from after the
sleep is issued, and I don't see where it was re-added.

  review needs-info

review: Needs Information
74. By Martin Pitt

do upower pkg-config check in the same block as the other libraries

75. By Martin Pitt

use g_strcmp0() for robustness

Revision history for this message
Martin Pitt (pitti) wrote :

> It uses the _sync calls, but we have a requirement to make all DBus
> operations async in the various indicator code. I'm unclear whether
> up_client_get_can_suspend is sync or async.

It gets the property synchronously on the first call (i. e. during initialization of indicator-session, and then just returns the cached value. I. e. in the "changed" signal handler the property values are already in the UpClient object's cache and no D-Bus communication needs to happen at all.

> I generally prefer to check for all the libraries at once in
> configure.ac. I find that this frustrates users less as they get all
.> the errors at once instead of getting one error, the next error, as they
> go through the configure script.

Fixed, r74.

> It should really use g_strcmp0 instead of strcmp as it protects from
> NULL strings which will otherwise be crashers.

Fixed, r75.

> It seems that the screensaver_unthrottle() was removed from after the
> sleep is issued, and I don't see where it was re-added.

Right after the up_client_{suspend,hibernate}_sync() call in machine_sleep(), since the callbacks disappeared.

review: Needs Resubmitting
Revision history for this message
Ted Gould (ted) wrote :

On Tue, 2010-02-16 at 15:28 +0000, Martin Pitt wrote:
> Review: Resubmit
> > It uses the _sync calls, but we have a requirement to make all DBus
> > operations async in the various indicator code. I'm unclear whether
> > up_client_get_can_suspend is sync or async.
>
> It gets the property synchronously on the first call (i. e. during
> initialization of indicator-session, and then just returns the cached
> value. I. e. in the "changed" signal handler the property values are
> already in the UpClient object's cache and no D-Bus communication
> needs to happen at all.

So I went and grabbed the upower code and basically none of this is
Async. At all. I'd love to use the libupower library so that we're in
a better place with the interface, but man:

ted@shi:~/Packaging/upower/upower-0.9.0+git20100216.b9bb78$ rgrep _async
*
src/up-daemon.c: ret = g_spawn_command_line_async (command, &error);
ted@shi:~/Packaging/upower/upower-0.9.0+git20100216.b9bb78$

I'm not sure what to do here. David, do you have opinion? I'd hate to
rewrite the PolicyKit code, but we've made it a core architectural point
to only use async DBus. I doubt we could patch libupower at this point
as it'd be a pretty big patch.

Revision history for this message
Martin Pitt (pitti) wrote :

> On Tue, 2010-02-16 at 15:28 +0000, Martin Pitt wrote:

> So I went and grabbed the upower code and basically none of this is
> Async. At all.

All the properties are cached on the client side, though, so reading properties is usually not using D-Bus at all (except for the first time, as I said).

The suspend/hibernate calls are also sync. libupower-glib deliberately does it that way, since it makes the program structure so much easier, since the machine will just die/stop underneath you anyway, and it saves you from dealing with all the async handlers.

> I'm not sure what to do here. David, do you have opinion? I'd hate to
> rewrite the PolicyKit code, but we've made it a core architectural point
> to only use async DBus.

OK, deferring to David for the general decision.

You don't actually need to ask PolicyKit yourself, though. I added upower D-Bus methods {Suspend,Hibernate}Allowed() methods which return a boolean, which do the polkit checks.

> I doubt we could patch libupower at this point as it'd be a pretty big patch.

Might be worth discussing with Richard upstream, but I don't think he'd be happy about this. With my upstream hat on, I certainly wouldn't accept it, since it's not what libupower-glib is designed to be. The current API is meant to be an easy and robust integration into a glib/gobject context, and avoiding all unnecessary D-Bus calls. Adding a series of async D-Bus calls to it would make it (1) unnecessarily more complex, and (2) not provide any significant benefit over D-Bus directly.

So in summary, if i-s wants to use async calls only, we should keep the direct D-Bus interface, and need to add a call to {Suspend,Hibernate}Allowed().

Thanks!

Revision history for this message
David Barth (dbarth) wrote :

Ted Gould wrote:
> On Tue, 2010-02-16 at 15:28 +0000, Martin Pitt wrote:
>
>> Review: Resubmit
>>
>>> It uses the _sync calls, but we have a requirement to make all DBus
>>> operations async in the various indicator code. I'm unclear whether
>>> up_client_get_can_suspend is sync or async.
>>>
>> It gets the property synchronously on the first call (i. e. during
>> initialization of indicator-session, and then just returns the cached
>> value. I. e. in the "changed" signal handler the property values are
>> already in the UpClient object's cache and no D-Bus communication
>> needs to happen at all.
>>
>
> So I went and grabbed the upower code and basically none of this is
> Async. At all. I'd love to use the libupower library so that we're in
> a better place with the interface, but man:
>
> ted@shi:~/Packaging/upower/upower-0.9.0+git20100216.b9bb78$ rgrep _async
> *
> src/up-daemon.c: ret = g_spawn_command_line_async (command, &error);
> ted@shi:~/Packaging/upower/upower-0.9.0+git20100216.b9bb78$
>
Ouch.
> I'm not sure what to do here. David, do you have opinion? I'd hate to
> rewrite the PolicyKit code, but we've made it a core architectural point
> to only use async DBus. I doubt we could patch libupower at this point
> as it'd be a pretty big patch.
>
Well, I guess then it means either keeping your async code, and...
ugh... adding the PK per-user policy bits (no idea how complex that can
be), or...

...adding a thread where calls to upower can block. The lib is not
advertised as being thread safe, but I haven't spotted big static
variables in the library source, so that may reasonably work.

David

Revision history for this message
Martin Pitt (pitti) wrote :

Guys,

I'll work on an alternative branch which ports to the upower D-Bus interface directly. Then you can pick what you like better.

Revision history for this message
Martin Pitt (pitti) wrote :

https://code.launchpad.net/~pitti/indicator-session/upower/+merge/19472 is a straightforward port to upower, but it does not yet fix bug 432598 yet. If you are serious about the full async thing, this would require yet another async call from the callback, and reading the response in another callback.

Revision history for this message
Ted Gould (ted) wrote :

Accepted merge 19472 so this one is not valid.

Unmerged revisions

75. By Martin Pitt

use g_strcmp0() for robustness

74. By Martin Pitt

do upower pkg-config check in the same block as the other libraries

73. By Martin Pitt

port to libupower-glib

Stop talking to DeviceKit-power directly. Use the glib client library instead,
which is much easier to use, and also respects the per-user PolicyKit settings
(LP #432598).

Also go straight to upower.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'configure.ac'
--- configure.ac 2010-02-11 16:47:17 +0000
+++ configure.ac 2010-02-16 15:30:33 +0000
@@ -29,6 +29,7 @@
29INDICATOR_REQUIRED_VERSION=0.3.029INDICATOR_REQUIRED_VERSION=0.3.0
30DBUSMENUGTK_REQUIRED_VERSION=0.2.230DBUSMENUGTK_REQUIRED_VERSION=0.2.2
31POLKIT_REQUIRED_VERSION=0.9231POLKIT_REQUIRED_VERSION=0.92
32UPOWER_REQUIRED_VERSION=0.9
3233
33PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION34PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION
34 indicator >= $INDICATOR_REQUIRED_VERSION35 indicator >= $INDICATOR_REQUIRED_VERSION
@@ -39,7 +40,8 @@
39DBUSMENUGLIB_REQUIRED_VERSION=0.1.140DBUSMENUGLIB_REQUIRED_VERSION=0.1.1
4041
41PKG_CHECK_MODULES(SESSIONSERVICE, dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION42PKG_CHECK_MODULES(SESSIONSERVICE, dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION
42 indicator >= $INDICATOR_REQUIRED_VERSION)43 indicator >= $INDICATOR_REQUIRED_VERSION
44 upower-glib >= $UPOWER_REQUIRED_VERSION)
4345
44AC_SUBST(SESSIONERVICE_CFLAGS)46AC_SUBST(SESSIONERVICE_CFLAGS)
45AC_SUBST(SESSIONERVICE_LIBS)47AC_SUBST(SESSIONERVICE_LIBS)
4648
=== modified file 'src/session-service.c'
--- src/session-service.c 2010-02-08 22:46:35 +0000
+++ src/session-service.c 2010-02-16 15:30:33 +0000
@@ -31,6 +31,8 @@
31#include <dbus/dbus-glib.h>31#include <dbus/dbus-glib.h>
32#include <dbus/dbus-glib-bindings.h>32#include <dbus/dbus-glib-bindings.h>
3333
34#include <upower.h>
35
34#include <libdbusmenu-glib/server.h>36#include <libdbusmenu-glib/server.h>
35#include <libdbusmenu-glib/menuitem.h>37#include <libdbusmenu-glib/menuitem.h>
36#include <libdbusmenu-glib/client.h>38#include <libdbusmenu-glib/client.h>
@@ -44,10 +46,6 @@
44#include "users-service-dbus.h"46#include "users-service-dbus.h"
45#include "lock-helper.h"47#include "lock-helper.h"
4648
47#define DKP_ADDRESS "org.freedesktop.DeviceKit.Power"
48#define DKP_OBJECT "/org/freedesktop/DeviceKit/Power"
49#define DKP_INTERFACE "org.freedesktop.DeviceKit.Power"
50
51#define GUEST_SESSION_LAUNCHER "/usr/share/gdm/guest-session/guest-session-launch"49#define GUEST_SESSION_LAUNCHER "/usr/share/gdm/guest-session/guest-session-launch"
5250
53#define LOCKDOWN_DIR "/desktop/gnome/lockdown"51#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
@@ -72,11 +70,7 @@
7270
73static DbusmenuMenuitem * root_menuitem = NULL;71static DbusmenuMenuitem * root_menuitem = NULL;
74static GMainLoop * mainloop = NULL;72static GMainLoop * mainloop = NULL;
75static DBusGProxy * dkp_main_proxy = NULL;73static UpClient * up_client = NULL;
76static DBusGProxy * dkp_prop_proxy = NULL;
77
78static DBusGProxyCall * suspend_call = NULL;
79static DBusGProxyCall * hibernate_call = NULL;
8074
81static DbusmenuMenuitem * hibernate_mi = NULL;75static DbusmenuMenuitem * hibernate_mi = NULL;
82static DbusmenuMenuitem * suspend_mi = NULL;76static DbusmenuMenuitem * suspend_mi = NULL;
@@ -131,15 +125,6 @@
131 }125 }
132}126}
133127
134/* A return from the command to sleep the system. Make sure
135 that we unthrottle the screensaver. */
136static void
137sleep_response (DBusGProxy * proxy, DBusGProxyCall * call, gpointer data)
138{
139 screensaver_unthrottle();
140 return;
141}
142
143/* Let's put this machine to sleep, with some info on how128/* Let's put this machine to sleep, with some info on how
144 it should sleep. */129 it should sleep. */
145static void130static void
@@ -147,105 +132,41 @@
147{132{
148 gchar * type = (gchar *)userdata;133 gchar * type = (gchar *)userdata;
149134
150 if (dkp_main_proxy == NULL) {135 if (up_client == NULL) {
151 g_warning("Can not %s as no DeviceKit Power Proxy", type);136 g_warning("Can not %s as we have no upower client", type);
152 }137 }
153138
154 screensaver_throttle(type);139 screensaver_throttle(type);
155 lock_screen(NULL, 0, NULL);140 lock_screen(NULL, 0, NULL);
156141
157 dbus_g_proxy_begin_call(dkp_main_proxy,142 if (g_strcmp0(type, "Suspend") == 0) {
158 type,143 up_client_suspend_sync(up_client, NULL, NULL);
159 sleep_response,144 } else {
160 NULL,145 up_client_hibernate_sync(up_client, NULL, NULL);
161 NULL,146 }
162 G_TYPE_INVALID);147 screensaver_unthrottle();
163148
164 return;149 return;
165}150}
166151
167/* A response to getting the suspend property */
168static void
169suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
170{
171 suspend_call = NULL;
172
173 GValue candoit = {0};
174 GError * error = NULL;
175 dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID);
176 if (error != NULL) {
177 g_warning("Unable to check suspend: %s", error->message);
178 g_error_free(error);
179 return;
180 }
181 g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false");
182
183 if (suspend_mi != NULL) {
184 dbusmenu_menuitem_property_set_value(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
185 }
186
187 return;
188}
189
190/* Response to getting the hibernate property */
191static void
192hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
193{
194 hibernate_call = NULL;
195
196 GValue candoit = {0};
197 GError * error = NULL;
198 dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID);
199 if (error != NULL) {
200 g_warning("Unable to check hibernate: %s", error->message);
201 g_error_free(error);
202 return;
203 }
204 g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false");
205
206 if (suspend_mi != NULL) {
207 dbusmenu_menuitem_property_set_value(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
208 }
209
210 return;
211}
212152
213/* A signal that we need to recheck to ensure we can still153/* A signal that we need to recheck to ensure we can still
214 hibernate and/or suspend */154 hibernate and/or suspend */
215static void155static void
216dpk_changed_cb (DBusGProxy * proxy, gpointer user_data)156up_changed_cb (UpClient * client, gpointer user_data)
217{157{
218 /* Start Async call to see if we can hibernate */158 GValue candoit = {0};
219 if (suspend_call == NULL) {159 g_value_init (&candoit, G_TYPE_BOOLEAN);
220 suspend_call = dbus_g_proxy_begin_call(dkp_prop_proxy,160
221 "Get",161 /* can we suspend? */
222 suspend_prop_cb,162 g_value_set_boolean(&candoit, up_client_get_can_suspend(up_client));
223 NULL,163 dbusmenu_menuitem_property_set_value(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
224 NULL,164 g_debug("upower changed: can suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false");
225 G_TYPE_STRING,165
226 DKP_INTERFACE,166 /* can we hibernate? */
227 G_TYPE_STRING,167 g_value_set_boolean(&candoit, up_client_get_can_hibernate(up_client));
228 "can-suspend",168 dbusmenu_menuitem_property_set_value(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
229 G_TYPE_INVALID,169 g_debug("upower changed: can hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false");
230 G_TYPE_VALUE,
231 G_TYPE_INVALID);
232 }
233
234 /* Start Async call to see if we can suspend */
235 if (hibernate_call == NULL) {
236 hibernate_call = dbus_g_proxy_begin_call(dkp_prop_proxy,
237 "Get",
238 hibernate_prop_cb,
239 NULL,
240 NULL,
241 G_TYPE_STRING,
242 DKP_INTERFACE,
243 G_TYPE_STRING,
244 "can-hibernate",
245 G_TYPE_INVALID,
246 G_TYPE_VALUE,
247 G_TYPE_INVALID);
248 }
249170
250 return;171 return;
251}172}
@@ -254,39 +175,17 @@
254 DKp checking. We're even setting up the calls for the props175 DKp checking. We're even setting up the calls for the props
255 we need */176 we need */
256static void177static void
257setup_dkp (void) {178setup_up (void) {
258 DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);179 up_client = up_client_new();
259 g_return_if_fail(bus != NULL);180 g_return_if_fail(up_client != NULL);
260
261 if (dkp_main_proxy == NULL) {
262 dkp_main_proxy = dbus_g_proxy_new_for_name(bus,
263 DKP_ADDRESS,
264 DKP_OBJECT,
265 DKP_INTERFACE);
266 }
267 g_return_if_fail(dkp_main_proxy != NULL);
268
269 if (dkp_prop_proxy == NULL) {
270 dkp_prop_proxy = dbus_g_proxy_new_for_name(bus,
271 DKP_ADDRESS,
272 DKP_OBJECT,
273 DBUS_INTERFACE_PROPERTIES);
274 }
275 g_return_if_fail(dkp_prop_proxy != NULL);
276181
277 /* Connect to changed signal */182 /* Connect to changed signal */
278 dbus_g_proxy_add_signal(dkp_main_proxy,183 g_signal_connect (up_client, "changed",
279 "Changed",184 G_CALLBACK(up_changed_cb),
280 G_TYPE_INVALID);185 NULL);
281
282 dbus_g_proxy_connect_signal(dkp_main_proxy,
283 "Changed",
284 G_CALLBACK(dpk_changed_cb),
285 NULL,
286 NULL);
287186
288 /* Force an original "changed" event */187 /* Force an original "changed" event */
289 dpk_changed_cb(dkp_main_proxy, NULL);188 up_changed_cb(up_client, NULL);
290189
291 return;190 return;
292}191}
@@ -639,7 +538,7 @@
639 G_CALLBACK (user_removed),538 G_CALLBACK (user_removed),
640 root_menuitem);539 root_menuitem);
641540
642 setup_dkp();541 setup_up();
643542
644 DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);543 DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);
645 dbusmenu_server_set_root(server, root_menuitem);544 dbusmenu_server_set_root(server, root_menuitem);

Subscribers

People subscribed via source and target branches