[systemd-commits] 2 commits - src/libsystemd src/login src/systemd
Lennart Poettering
lennart at kemper.freedesktop.org
Fri Feb 21 12:14:17 PST 2014
src/libsystemd/sd-event/sd-event.c | 72 +++++++++++++++++++++++++++++++++++++
src/login/logind-action.c | 4 ++
src/login/logind-button.c | 70 +++++++++++++++++++++++------------
src/login/logind-button.h | 7 ++-
src/login/logind.c | 55 ++++++++--------------------
src/systemd/sd-event.h | 1
6 files changed, 142 insertions(+), 67 deletions(-)
New commits:
commit ed4ba7e4f652150310d062ffbdfefb4521ce1054
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Feb 21 21:10:00 2014 +0100
logind: when we wake up from suspend and the lid is still closed, go to sleep immediately again
This is quite useful on laptops such as the Lenovo Yoga, where the power
button is placed on the front side of the laptop and can be pressed by
accident even if the lid is closed.
This reworks a bit of the logind logic to repeatedly try to suspend the
system as long as a lid is closed. We use the new "post" event source
for this, so that we don't keep things busy.
This also adds some code to check the lid status on boot, so that a
powered-off machine that is accidentaly powered on goes into suspend
immediately.
Yay! From now on I can put my Yoga safely in my backpack without fearing
that it might turn itself on and drain the battery.
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index 7744add..3bad922 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -80,6 +80,10 @@ int manager_handle_action(
/* Locking is handled differently from the rest. */
if (handle == HANDLE_LOCK) {
+
+ if (!is_edge)
+ return 0;
+
log_info("Locking sessions...");
session_send_lock_all(m, true);
return 1;
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index 80236c4..720071a 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -66,7 +66,8 @@ void button_free(Button *b) {
hashmap_remove(b->manager->buttons, b->name);
- sd_event_source_unref(b->event_source);
+ sd_event_source_unref(b->io_event_source);
+ sd_event_source_unref(b->check_event_source);
if (b->fd >= 0) {
/* If the device has been unplugged close() returns
@@ -96,24 +97,30 @@ int button_set_seat(Button *b, const char *sn) {
return 0;
}
-static int button_handle(
- Button *b,
- InhibitWhat inhibit_key,
- HandleAction handle,
- bool ignore_inhibited,
- bool is_edge) {
+static int button_recheck(sd_event_source *e, void *userdata) {
+ Button *b = userdata;
- int r;
+ assert(b);
+ assert(b->lid_closed);
+
+ manager_handle_action(b->manager, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, false);
+ return 1;
+}
+static int button_install_check_event_source(Button *b) {
+ int r;
assert(b);
- r = manager_handle_action(b->manager, inhibit_key, handle, ignore_inhibited, is_edge);
- if (r > 0)
- /* We are executing the operation, so make sure we don't
- * execute another one until the lid is opened/closed again */
- b->lid_close_queued = false;
+ /* Install a post handler, so that we keep rechecking as long as the lid is closed. */
- return 0;
+ if (b->check_event_source)
+ return 0;
+
+ r = sd_event_add_post(b->manager->event, &b->check_event_source, button_recheck, b);
+ if (r < 0)
+ return r;
+
+ return sd_event_source_set_priority(b->check_event_source, SD_EVENT_PRIORITY_IDLE+1);
}
static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
@@ -142,7 +149,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
MESSAGE_ID(SD_MESSAGE_POWER_KEY),
NULL);
- button_handle(b, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
+ manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
break;
/* The kernel is a bit confused here:
@@ -157,7 +164,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
MESSAGE_ID(SD_MESSAGE_SUSPEND_KEY),
NULL);
- button_handle(b, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
+ manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
break;
case KEY_SUSPEND:
@@ -166,7 +173,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
MESSAGE_ID(SD_MESSAGE_HIBERNATE_KEY),
NULL);
- button_handle(b, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
+ manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
break;
}
@@ -178,8 +185,9 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
MESSAGE_ID(SD_MESSAGE_LID_CLOSED),
NULL);
- b->lid_close_queued = true;
- button_handle(b, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, true);
+ b->lid_closed = true;
+ manager_handle_action(b->manager, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, true);
+ button_install_check_event_source(b);
}
} else if (ev.type == EV_SW && ev.value == 0) {
@@ -190,7 +198,8 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
MESSAGE_ID(SD_MESSAGE_LID_OPENED),
NULL);
- b->lid_close_queued = false;
+ b->lid_closed = false;
+ b->check_event_source = sd_event_source_unref(b->check_event_source);
}
}
@@ -222,7 +231,7 @@ int button_open(Button *b) {
goto fail;
}
- r = sd_event_add_io(b->manager->event, &b->event_source, b->fd, EPOLLIN, button_dispatch, b);
+ r = sd_event_add_io(b->manager->event, &b->io_event_source, b->fd, EPOLLIN, button_dispatch, b);
if (r < 0) {
log_error("Failed to add button event: %s", strerror(-r));
goto fail;
@@ -238,11 +247,22 @@ fail:
return r;
}
-int button_recheck(Button *b) {
+int button_check_lid(Button *b) {
+ uint8_t switches[SW_MAX/8+1] = {};
assert(b);
- if (!b->lid_close_queued)
- return 0;
+ if (b->fd < 0)
+ return -EINVAL;
+
+ if (ioctl(b->fd, EVIOCGSW(sizeof(switches)), switches) < 0)
+ return -errno;
- return button_handle(b, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, false);
+ b->lid_closed = (switches[SW_LID/8] >> (SW_LID % 8)) & 1;
+
+ if (b->lid_closed) {
+ manager_handle_action(b->manager, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, true);
+ button_install_check_event_source(b);
+ }
+
+ return 0;
}
diff --git a/src/login/logind-button.h b/src/login/logind-button.h
index 824106c..e85aa81 100644
--- a/src/login/logind-button.h
+++ b/src/login/logind-button.h
@@ -30,17 +30,18 @@ typedef struct Button Button;
struct Button {
Manager *manager;
- sd_event_source *event_source;
+ sd_event_source *io_event_source;
+ sd_event_source *check_event_source;
char *name;
char *seat;
int fd;
- bool lid_close_queued;
+ bool lid_closed;
};
Button* button_new(Manager *m, const char *name);
void button_free(Button*b);
int button_open(Button *b);
-int button_recheck(Button *b);
int button_set_seat(Button *b, const char *sn);
+int button_check_lid(Button *b);
diff --git a/src/login/logind.c b/src/login/logind.c
index 28d7058..9cbd9e8 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -73,32 +73,28 @@ Manager *manager_new(void) {
m->busnames = set_new(string_hash_func, string_compare_func);
if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
- !m->user_units || !m->session_units) {
- manager_free(m);
- return NULL;
- }
+ !m->user_units || !m->session_units)
+ goto fail;
m->kill_exclude_users = strv_new("root", NULL);
- if (!m->kill_exclude_users) {
- manager_free(m);
- return NULL;
- }
+ if (!m->kill_exclude_users)
+ goto fail;
m->udev = udev_new();
- if (!m->udev) {
- manager_free(m);
- return NULL;
- }
+ if (!m->udev)
+ goto fail;
r = sd_event_default(&m->event);
- if (r < 0) {
- manager_free(m);
- return NULL;
- }
+ if (r < 0)
+ goto fail;
sd_event_set_watchdog(m->event, true);
return m;
+
+fail:
+ manager_free(m);
+ return NULL;
}
void manager_free(Manager *m) {
@@ -968,6 +964,7 @@ int manager_startup(Manager *m) {
Seat *seat;
Session *session;
User *user;
+ Button *button;
Inhibitor *inhibitor;
Iterator i;
@@ -1041,31 +1038,14 @@ int manager_startup(Manager *m) {
HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
inhibitor_start(inhibitor);
+ HASHMAP_FOREACH(button, m->buttons, i)
+ button_check_lid(button);
+
manager_dispatch_idle_action(NULL, 0, m);
return 0;
}
-static int manager_recheck_buttons(Manager *m) {
- Iterator i;
- Button *b;
- int r = 0;
-
- assert(m);
-
- HASHMAP_FOREACH(b, m->buttons, i) {
- int q;
-
- q = button_recheck(b);
- if (q > 0)
- return 1;
- if (q < 0)
- r = q;
- }
-
- return r;
-}
-
int manager_run(Manager *m) {
int r;
@@ -1085,9 +1065,6 @@ int manager_run(Manager *m) {
if (manager_dispatch_delayed(m) > 0)
continue;
- if (manager_recheck_buttons(m) > 0)
- continue;
-
if (m->action_what != 0 && !m->action_job) {
usec_t x, y;
commit 6e9feda30d6d5c4aa9908d458c92eb0daf90eb3a
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Feb 21 21:06:09 2014 +0100
event: add new kind of event source called "post"
This new event source is triggered by the dispatching of any non-post
event source. It can thus be used to do clean-up or recheck work,
triggered by any other event source having been executed.
This is different from "defer" event source which are unconditionally
triggered as long as they are enabled. A "defer" event source that does
nothing will result in the event loop busy looping unless it is turned
off eventually. This is different for "post" event sources that will be
only triggered when some other non-post ran, and will thus not keep the
event loop busy on its own.
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 1f039bc..253923d 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -32,6 +32,7 @@
#include "util.h"
#include "time-util.h"
#include "missing.h"
+#include "set.h"
#include "sd-event.h"
@@ -45,6 +46,7 @@ typedef enum EventSourceType {
SOURCE_SIGNAL,
SOURCE_CHILD,
SOURCE_DEFER,
+ SOURCE_POST,
SOURCE_EXIT,
SOURCE_WATCHDOG
} EventSourceType;
@@ -97,6 +99,9 @@ struct sd_event_source {
} defer;
struct {
sd_event_handler_t callback;
+ } post;
+ struct {
+ sd_event_handler_t callback;
unsigned prioq_index;
} exit;
};
@@ -134,6 +139,8 @@ struct sd_event {
Hashmap *child_sources;
unsigned n_enabled_child_sources;
+ Set *post_sources;
+
Prioq *exit;
pid_t original_pid;
@@ -350,6 +357,7 @@ static void event_free(sd_event *e) {
free(e->signal_sources);
hashmap_free(e->child_sources);
+ set_free(e->post_sources);
free(e);
}
@@ -524,6 +532,10 @@ static void source_free(sd_event_source *s) {
/* nothing */
break;
+ case SOURCE_POST:
+ set_remove(s->event->post_sources, s);
+ break;
+
case SOURCE_EXIT:
prioq_remove(s->event->exit, s, &s->exit.prioq_index);
break;
@@ -957,6 +969,43 @@ _public_ int sd_event_add_defer(
return 0;
}
+_public_ int sd_event_add_post(
+ sd_event *e,
+ sd_event_source **ret,
+ sd_event_handler_t callback,
+ void *userdata) {
+
+ sd_event_source *s;
+ int r;
+
+ assert_return(e, -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(ret, -EINVAL);
+ assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
+ assert_return(!event_pid_changed(e), -ECHILD);
+
+ r = set_ensure_allocated(&e->post_sources, trivial_hash_func, trivial_compare_func);
+ if (r < 0)
+ return r;
+
+ s = source_new(e, SOURCE_POST);
+ if (!s)
+ return -ENOMEM;
+
+ s->post.callback = callback;
+ s->userdata = userdata;
+ s->enabled = SD_EVENT_ON;
+
+ r = set_put(e->post_sources, s);
+ if (r < 0) {
+ source_free(s);
+ return r;
+ }
+
+ *ret = s;
+ return 0;
+}
+
_public_ int sd_event_add_exit(
sd_event *e,
sd_event_source **ret,
@@ -1246,6 +1295,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
break;
case SOURCE_DEFER:
+ case SOURCE_POST:
s->enabled = m;
break;
@@ -1304,6 +1354,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
break;
case SOURCE_DEFER:
+ case SOURCE_POST:
s->enabled = m;
break;
@@ -1779,6 +1830,23 @@ static int source_dispatch(sd_event_source *s) {
return r;
}
+ if (s->type != SOURCE_POST) {
+ sd_event_source *z;
+ Iterator i;
+
+ /* If we execute a non-post source, let's mark all
+ * post sources as pending */
+
+ SET_FOREACH(z, s->event->post_sources, i) {
+ if (z->enabled == SD_EVENT_OFF)
+ continue;
+
+ r = source_set_pending(z, true);
+ if (r < 0)
+ return r;
+ }
+ }
+
if (s->enabled == SD_EVENT_ONESHOT) {
r = sd_event_source_set_enabled(s, SD_EVENT_OFF);
if (r < 0)
@@ -1825,6 +1893,10 @@ static int source_dispatch(sd_event_source *s) {
r = s->defer.callback(s, s->userdata);
break;
+ case SOURCE_POST:
+ r = s->post.callback(s, s->userdata);
+ break;
+
case SOURCE_EXIT:
r = s->exit.callback(s, s->userdata);
break;
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index 68c52c5..45c3608 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -82,6 +82,7 @@ int sd_event_add_realtime(sd_event *e, sd_event_source **s, uint64_t usec, uint6
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
+int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_run(sd_event *e, uint64_t timeout);
More information about the systemd-commits
mailing list