[RFC]: Enhanced User Sessions and session shutdown

James Hunt james.hunt at ubuntu.com
Thu Jan 24 14:18:14 UTC 2013


Hi Steve,

On 24/01/13 07:25, Steve Langasek wrote:
> Hi James,
> 
> On Fri, Jan 18, 2013 at 05:35:45PM +0000, James Hunt wrote:
>> I've recently updated the spec above to include details of session shutdown [1].
>> If anyone has comments, please weigh in:
> 
>> https://wiki.ubuntu.com/FoundationsTeam/Specs/RaringUpstartUserSessions#Desktop_Session_Shutdown
> 
>> Note that on Ubuntu, when the gnome-session job ends, gnome-session will
>> potentially first signal ConsoleKit to shutdown the system. This will ultimately
>> result in the display manager (lightdm on Ubuntu) sending SIGTERM to each
>> Session Init [2] which should preclude the need for a final "shutdown" job that
>> reacts to the session-exiting event, although it may be necessary to modify the
>> 'kill timeout' for the lightdm job.
> 
> You write here:
> 
>   With Upstart sessions, the Session Init will be terminated by:
> 
>     * The desktop session sending an initctl command request to shutdown.
>     * The Session Init Instance will react to this, stop all the jobs and
>       then exit itself, closing the session in the process.
> 
> I don't think that's accurate.  The decision about whether or not the system
> can be shutdown/rebooted by the user needs to be made via system-level
> policy; the shutdown request thus needs to be referred to a system-level
> service before we shut down *any* jobs from the session init.
I think there is some confusion here between session end and system shutdown.
The 2 bullets you're referencing are under the heading 'Desktop Session
Shutdown', not 'system shutdown'. To be clear the 'initctl shutdown' command is
a request to shutdown the Session Init, but in certain circumstances (where
--type is 'shutdown' or 'reboot'), that action may also trigger a system shutdown.

I think the confusion has arisen as I didn't qualify that 'shutdown' refers to
the *session* (not the system) in that first bullet. I've now clarified that in
the spec.

> Only once the system init has been signalled to change runlevels via the
> shutdown command, and the lightdm service has been asked to stop, should the
> session init start generate a session-end event (in response to being
> signalled itself).
Right, but this does not handle the case where the user simply "logs out".

> 
> So the first half of the architecture should remain entirely unchanged, we
> only want to switch out some of the components:
> 
>   * The indicator, or the power button dialog calls 'initctl shutdown' with
>     the correct logout, reboot, or shutdown '--type' argument.
>   * The session init checks whether the shutdown has been blocked with the
>     org.gnome.SessionManager.Inhibit() D-Bus API call (which something
>     associated with the upstart session will need to implement).
This would have to be handled by either a job or some sort of bridge to avoid
making Upstart itself dependent on Gnome (that's why the current spec allows
gnome-session to continue to handle the inhibiting bits itself).

>   * Once the shutdown is not blocked, on shutdown/reboot:
>     * the session init, or a job acting on its behalf, calls the
>       corresponding method of ConsoleKit or systemd.
Again, the spec allows a job to perform this action.

>     * ConsoleKit ultimately calls /usr/lib/ConsoleKit/scripts/ck-system-stop,
>       which in turn calls shutdown(8).
>     * shutdown(8) emits the "runlevel" Upstart event.
>     * This triggers stopping of the lightdm jobs (among others)
>     * The lightdm job sends SIGTERM to all clients (upstart session init
>       processes).
>     * The session init generates a session-end event, which is processed
>       normally.
>     * Either the user jobs correctly end in a timely manner in response to
>       this event; or they do not, in which case they are instead reaped by
>       /etc/init.d/sendsigs.
I'm not clear what you mean here - are you saying that the Session Init should
*not* send any signals to running jobs? If so, this could only work for the
shutdown/reboot scenario (for logout we still need to honour kill_timeout). It
also means that any jobs which do not specify 'stop on' will linger
unnecessarily long. Note too that even in the shutdown/reboot scenario, if we
just wait to die, we're still going to artificially slow down the shutdown since
lightdm will wait 5 seconds for its clients to die. Since that value is the same
as the lightdm kill timeout, we could therefore cause a delay of that many
seconds where we could potentially exit a lot sooner.

  There should not be any need for complex
>       timeout handling in the session init itself.
The reason for this is threefold:

- it allows upstart to give each job its allocated kill timeout before sending
SIGKILL.
- it allows for a faster shutdown.
- it ensures that the Session Init doesn't wait forever to shutdown (except
where explicitly requested by $WAIT).

  (Note however that
>       /etc/init.d/sendsigs probably needs some changes in order to not go
>       killing user jobs - and session init processes - with *no* delay,
>       depriving them of the opportunity to shut down gracefully.)
>     * If all session jobs exit and the session init is quiesced (i.e., no
>       remaining "blocked" events), the session init exits.  Otherwise, it
>       will be killed externally (by lightdm or by sendsigs).
Again, this only caters for the system shutdown scenario - we cannot wait
forever for blocked events in the "logout" scenario as those events may never
arrive (for example 'stop on session-end and never-emitted') thus causing the
Session Init to never exit, hence the need for timeouts.

>     * lightdm exits.
>     * The rest of the shutdown sequence completes.
Another source of confusion is that this doesn't seem to be how it currently
happens in Ubuntu - I raised a bug on gnome-session [1] recently (which does
suggest the system should work as you outline: desktop team investigating).

> 
> This architecture has the following important properties:
> 
>  - We don't assume the shutdown command has been accepted (and start killing
>    user jobs in response) until acknowledged as such by a root daemon
>  - We preserve the existing interface for inhibiting shutdown that's used by
>    existing software
>  - We aren't relying on the user's session init to do the cleanup, beyond
>    making sure it tells the jobs to shutdown; instead the logic for timeout
>    handling is all at the system level, where it needs to be.
> 
> Does this make sense?

So, what we're now saying is that for a logout we want to:

(1) stop all running jobs.
(2) exit as quickly as possible, but don't let anything block the exit (unless
explicitly requested with $WAIT).
(3) return control to lightdm.

The current spec handles that I think.

Whereas for a shutdown/reboot we want to:

(a) signal ConsoleKit via a job.
(b) only start the shutdown sequence when signalled by lightdm, indicating that
it is stopping.
(c) exit as quickly as possible, ideally before being SIGKILL'ed by lightdm but
only if $WAIT and the kill timeouts for running jobs permit.

The problems with the shutdown/reboot steps though are:

(*) - $WAIT and kill timeout is ignored: if and when lightdm signals the Session
Init, the window of opportunity to stop all jobs is 5 seconds since:

- lightdm will SIGKILL the Session Init after this period.
- even if lightdm doesn't, the kill timeout for the lightdm job is 5 seconds too
so lightdm will die within 5 seconds regardless.

(*) - how we handle gnome-sessions's Inhibit? We can query if the session is
inhibited, but we're not stopping the gnome-session job yet.

The following suggests we don't have to, but I think we need further input on
this angle:

https://live.gnome.org/SessionManagement/GnomeSession#A5._QueryEndSession

All this aside, the shutdown/reboot scenario is simplified such that we don't
need to re-enable jobs in the quiescent mode (ugly) since the 'shutdown' job can
be run immediately and all this job would do is call the appropriate ConsoleKit
D-Bus API. That job will finish almost immediately as there is no return value
from the CK D-Bus methods to control shutdown.

Kind regards,

James.

[1] - https://bugs.launchpad.net/ubuntu/+source/gnome-session/+bug/1101154
--
James Hunt
____________________________________
http://upstart.ubuntu.com/cookbook
http://upstart.ubuntu.com/cookbook/upstart_cookbook.pdf



More information about the upstart-devel mailing list