diff options
author | Lennart Poettering <lennart@poettering.net> | 2009-08-11 04:02:33 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2009-08-12 17:10:12 +0200 |
commit | b4f893eb294883909759fc9fd825eade1a9f308c (patch) | |
tree | 9cec43fb26d8bb3269c1b0dda49404d0bc001a1a | |
parent | 76f0578e7a497e569438316703df254f84b548a0 (diff) |
Add seat.d/ callout directory and guarantee we dump the database before callout invocationHEADmaster
This adds a callout directory called seat.d/ that follows the basic
session.d/ semantics but works on seats instead of sessions.
As replacement for the old session.d/ 'session_active_changed'
semantics seat.d/ knows 'seat_active_session_changed'. Which combines
the two callouts necessary for session_active_changed into one. This has
various advantages: it's not as racy, allows the suppressing of ACL
permission changes when switching between sessions of the same user,
reduces the amount of disk IO and finally is less ugly.
This patch also moves all callout invocations into the CkManager. This
has the advantage that we can guarantee to have fully dumped the CK
database before the callout.
In summary, the session.d/ directory will now get two types of callout
invocations:
session_added
session_removed
In contrast, seat.d/ gets three types:
seat_added
seat_removed
seat_active_session_changed
The 'seat_active_session_changed' callout type gets two sets of
environment variables describing the old resp. the new session that is
active. Either set can be left out if no session was active before, or
no session will be active after the switch. This is similar to the logic
behind D-Bus' NameOwnerChanged.
This patch duplicates CkSeat's 'session-removed' signal into
'session-removed-full' (and friends). Reason for that is that the signal
forwarded via D-Bus needs the session id as string while the callout
code needs the session itself as object. Since at the time of invocation
the CkSeat is no longer in the seats hashtable it is hence necessary to
pass the object in as argument to the signal handlers, which makes this
duplification necessary to not confuse dbus-glib. For a similar reason
'active-session-changed' is duplicated as well.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/ck-manager.c | 56 | ||||
-rw-r--r-- | src/ck-marshal.list | 1 | ||||
-rw-r--r-- | src/ck-seat.c | 161 | ||||
-rw-r--r-- | src/ck-seat.h | 5 |
5 files changed, 200 insertions, 25 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index cbe8a09..6ab05c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -205,5 +205,7 @@ MAINTAINERCLEANFILES = \ install-data-local: -mkdir -p $(DESTDIR)$(sysconfdir)/ConsoleKit/run-session.d -mkdir -p $(DESTDIR)$(prefix)/lib/ConsoleKit/run-session.d + -mkdir -p $(DESTDIR)$(sysconfdir)/ConsoleKit/run-seat.d + -mkdir -p $(DESTDIR)$(prefix)/lib/ConsoleKit/run-seat.d -mkdir -p $(DESTDIR)$(localstatedir)/run/ConsoleKit -mkdir -p $(DESTDIR)$(localstatedir)/log/ConsoleKit diff --git a/src/ck-manager.c b/src/ck-manager.c index 440163b..4b7200b 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -1228,29 +1228,50 @@ ck_manager_can_stop (CkManager *manager, } static void -on_seat_active_session_changed (CkSeat *seat, - const char *ssid, - CkManager *manager) +on_seat_active_session_changed_full (CkSeat *seat, + CkSession *old_session, + CkSession *session, + CkManager *manager) { + char *ssid = NULL; + + if (session != NULL) { + ck_session_get_id (session, &ssid, NULL); + } + ck_manager_dump (manager); + ck_seat_run_programs (seat, old_session, session, "seat_active_session_changed"); + log_seat_active_session_changed_event (manager, seat, ssid); } static void -on_seat_session_added (CkSeat *seat, - const char *ssid, - CkManager *manager) +on_seat_session_added_full (CkSeat *seat, + CkSession *session, + CkManager *manager) { + char *ssid = NULL; + + ck_session_get_id (session, &ssid, NULL); + ck_manager_dump (manager); + ck_session_run_programs (session, "session_added"); + log_seat_session_added_event (manager, seat, ssid); } static void -on_seat_session_removed (CkSeat *seat, - const char *ssid, - CkManager *manager) +on_seat_session_removed_full (CkSeat *seat, + CkSession *session, + CkManager *manager) { + char *ssid = NULL; + + ck_session_get_id (session, &ssid, NULL); + ck_manager_dump (manager); + ck_session_run_programs (session, "session_removed"); + log_seat_session_removed_event (manager, seat, ssid); } @@ -1276,9 +1297,9 @@ static void connect_seat_signals (CkManager *manager, CkSeat *seat) { - g_signal_connect (seat, "active-session-changed", G_CALLBACK (on_seat_active_session_changed), manager); - g_signal_connect (seat, "session-added", G_CALLBACK (on_seat_session_added), manager); - g_signal_connect (seat, "session-removed", G_CALLBACK (on_seat_session_removed), manager); + g_signal_connect (seat, "active-session-changed-full", G_CALLBACK (on_seat_active_session_changed_full), manager); + g_signal_connect (seat, "session-added-full", G_CALLBACK (on_seat_session_added_full), manager); + g_signal_connect (seat, "session-removed-full", G_CALLBACK (on_seat_session_removed_full), manager); g_signal_connect (seat, "device-added", G_CALLBACK (on_seat_device_added), manager); g_signal_connect (seat, "device-removed", G_CALLBACK (on_seat_device_removed), manager); } @@ -1287,9 +1308,9 @@ static void disconnect_seat_signals (CkManager *manager, CkSeat *seat) { - g_signal_handlers_disconnect_by_func (seat, on_seat_active_session_changed, manager); - g_signal_handlers_disconnect_by_func (seat, on_seat_session_added, manager); - g_signal_handlers_disconnect_by_func (seat, on_seat_session_removed, manager); + g_signal_handlers_disconnect_by_func (seat, on_seat_active_session_changed_full, manager); + g_signal_handlers_disconnect_by_func (seat, on_seat_session_added_full, manager); + g_signal_handlers_disconnect_by_func (seat, on_seat_session_removed_full, manager); g_signal_handlers_disconnect_by_func (seat, on_seat_device_added, manager); g_signal_handlers_disconnect_by_func (seat, on_seat_device_removed, manager); } @@ -1325,7 +1346,9 @@ add_new_seat (CkManager *manager, g_debug ("Added seat: %s kind:%d", sid, kind); ck_manager_dump (manager); + ck_seat_run_programs (seat, NULL, NULL, "seat_added"); + g_debug ("Emitting seat-added: %s", sid); g_signal_emit (manager, signals [SEAT_ADDED], 0, sid); log_seat_added_event (manager, seat); @@ -1366,6 +1389,7 @@ remove_seat (CkManager *manager, } ck_manager_dump (manager); + ck_seat_run_programs (seat, NULL, NULL, "seat_removed"); g_debug ("Emitting seat-removed: %s", sid); g_signal_emit (manager, signals [SEAT_REMOVED], 0, sid); @@ -2429,7 +2453,9 @@ add_seat_for_file (CkManager *manager, g_debug ("Added seat: %s", sid); ck_manager_dump (manager); + ck_seat_run_programs (seat, NULL, NULL, "seat_added"); + g_debug ("Emitting seat-added: %s", sid); g_signal_emit (manager, signals [SEAT_ADDED], 0, sid); log_seat_added_event (manager, seat); diff --git a/src/ck-marshal.list b/src/ck-marshal.list index f9eed10..7f60efc 100644 --- a/src/ck-marshal.list +++ b/src/ck-marshal.list @@ -1,2 +1,3 @@ VOID:UINT,STRING BOOLEAN:POINTER +VOID:OBJECT,OBJECT diff --git a/src/ck-seat.c b/src/ck-seat.c index 27ccf14..4f5e63f 100644 --- a/src/ck-seat.c +++ b/src/ck-seat.c @@ -67,8 +67,11 @@ struct CkSeatPrivate enum { ACTIVE_SESSION_CHANGED, - SESSION_ADDED, + ACTIVE_SESSION_CHANGED_FULL, + SESSION_ADDED, /* Carries the session as path for D-Bus */ + SESSION_ADDED_FULL, /* Carries the session as CkSession for other uses */ SESSION_REMOVED, + SESSION_REMOVED_FULL, DEVICE_ADDED, DEVICE_REMOVED, LAST_SIGNAL @@ -480,15 +483,17 @@ static void change_active_session (CkSeat *seat, CkSession *session) { - char *ssid; + char *ssid; + CkSession *old_session; if (seat->priv->active_session == session) { return; } - if (seat->priv->active_session != NULL) { - ck_session_set_active (seat->priv->active_session, FALSE, NULL); - g_object_unref (seat->priv->active_session); + old_session = seat->priv->active_session; + + if (old_session != NULL) { + ck_session_set_active (old_session, FALSE, NULL); } seat->priv->active_session = session; @@ -502,8 +507,21 @@ change_active_session (CkSeat *seat, g_debug ("Active session changed: %s", ssid ? ssid : "(null)"); + /* The order of signal emission matters here. The manager + * dumps the database when receiving the + * 'active-session-changed-full' signal and does callout + * handling. dbus-glib will then send out a D-Bus on the + * 'active-session-changed' signal. Since the D-Bus signal + * must be sent when the database dump is finished it is + * important that the '-full' signalled is emitted first. */ + + g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED_FULL], 0, old_session, session); g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED], 0, ssid); + if (old_session != NULL) { + g_object_unref (old_session); + } + g_free (ssid); } @@ -586,9 +604,13 @@ ck_seat_remove_session (CkSeat *seat, * unref until the signal is emitted */ g_hash_table_steal (seat->priv->sessions, ssid); - ck_session_run_programs (session, "session_removed"); - g_debug ("Emitting session-removed: %s", ssid); + + /* The order of signal emission matters here, too, for similar + * reasons as for 'session-added'/'session-added-full'. See + * above. */ + + g_signal_emit (seat, signals [SESSION_REMOVED_FULL], 0, session); g_signal_emit (seat, signals [SESSION_REMOVED], 0, ssid); /* try to change the active session */ @@ -624,10 +646,12 @@ ck_seat_add_session (CkSeat *seat, g_signal_connect_object (session, "activate", G_CALLBACK (session_activate), seat, 0); /* FIXME: attach to property notify signals? */ - ck_session_run_programs (session, "session_added"); - g_debug ("Emitting added signal: %s", ssid); + /* The order of signal emission matters here, too. See + * above. */ + + g_signal_emit (seat, signals [SESSION_ADDED_FULL], 0, session); g_signal_emit (seat, signals [SESSION_ADDED], 0, ssid); maybe_update_active_session (seat); @@ -920,6 +944,15 @@ ck_seat_class_init (CkSeatClass *klass) g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + signals [ACTIVE_SESSION_CHANGED_FULL] = g_signal_new ("active-session-changed-full", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + ck_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, + 2, CK_TYPE_SESSION, CK_TYPE_SESSION); signals [SESSION_ADDED] = g_signal_new ("session-added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, @@ -929,6 +962,15 @@ ck_seat_class_init (CkSeatClass *klass) g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_OBJECT_PATH); + signals [SESSION_ADDED_FULL] = g_signal_new ("session-added-full", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, CK_TYPE_SESSION); signals [SESSION_REMOVED] = g_signal_new ("session-removed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, @@ -938,7 +980,15 @@ ck_seat_class_init (CkSeatClass *klass) g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_OBJECT_PATH); - + signals [SESSION_REMOVED_FULL] = g_signal_new ("session-removed-full", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, CK_TYPE_SESSION); signals [DEVICE_ADDED] = g_signal_new ("device-added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, @@ -1134,6 +1184,97 @@ ck_seat_new_from_file (const char *sid, } static void +env_add_session_info (CkSession *session, + const char *prefix, + char **extra_env, + int *n) +{ + char *s; + gboolean b; + guint u; + + if (session == NULL) { + return; + } + + if (ck_session_get_id (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sID=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_session_type (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sTYPE=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_unix_user (session, &u, NULL)) { + extra_env[(*n)++] = g_strdup_printf ("%sUSER_UID=%u", prefix, u); + g_free (s); + } + + if (ck_session_get_display_device (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sDISPLAY_DEVICE=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_x11_display_device (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sX11_DISPLAY_DEVICE=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_x11_display (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sX11_DISPLAY=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_remote_host_name (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sREMOTE_HOST_NAME=%s", prefix, s); + g_free (s); + } + + if (ck_session_is_local (session, &b, NULL)) + extra_env[(*n)++] = g_strdup_printf ("%sIS_LOCAL=%s", prefix, b ? "true" : "false"); +} + +void +ck_seat_run_programs (CkSeat *seat, + CkSession *old_session, + CkSession *new_session, + const char *action) +{ + int n; + char *extra_env[18]; /* be sure to adjust this as needed when + * you add more variables to the callout's + * environment */ + + n = 0; + + extra_env[n++] = g_strdup_printf ("CK_SEAT_ID=%s", seat->priv->id); + + /* Callout scripts/binaries should check if CK_SEAT_SESSION_ID + * resp. CK_SEAT_OLD_SESSON_ID is set to figure out if there + * will be an active session after the switch, or if there was + * one before. At least one of those environment variables + * will be set, possibly both. Only after checking these + * variables the script should check for the other session + * property variables. */ + + env_add_session_info (old_session, "CK_SEAT_OLD_SESSION_", extra_env, &n); + env_add_session_info (new_session, "CK_SEAT_SESSION_", extra_env, &n); + + extra_env[n++] = NULL; + + g_assert(n <= G_N_ELEMENTS(extra_env)); + + ck_run_programs (SYSCONFDIR "/ConsoleKit/run-seat.d", action, extra_env); + ck_run_programs (PREFIX "/lib/ConsoleKit/run-seat.d", action, extra_env); + + for (n = 0; extra_env[n] != NULL; n++) { + g_free (extra_env[n]); + } +} + +static void dump_seat_session_iter (char *id, CkSession *session, GString *str) diff --git a/src/ck-seat.h b/src/ck-seat.h index 47d10a7..fb9a955 100644 --- a/src/ck-seat.h +++ b/src/ck-seat.h @@ -93,6 +93,11 @@ CkSeat * ck_seat_new_with_devices (const char *sid, gboolean ck_seat_register (CkSeat *seat); +void ck_seat_run_programs (CkSeat *seat, + CkSession *old_session, + CkSession *new_session, + const char *action); + void ck_seat_dump (CkSeat *seat, GKeyFile *key_file); |