Bug 312947 - KDM never returns from the console login mode
Summary: KDM never returns from the console login mode
Status: RESOLVED FIXED
Alias: None
Product: kdm
Classification: Miscellaneous
Component: general (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR normal
Target Milestone: ---
Assignee: kdm bugs tracker
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-01-09 14:29 UTC by Алексей Шилин
Modified: 2014-03-28 17:06 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In: 4.11.8


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Алексей Шилин 2013-01-09 14:29:21 UTC
If I click the "Console login" menu item in KDM, it shuts X server down and switches to tty1, but never returns, regardless of whether I do log in or not.

Reproducible: Always

Steps to Reproduce:
1. Click the "Console login" menu item or press Alt+N.
2. Wait 40 seconds - the default login timeout.
3. Log in and out.
4. Wait 10 seconds.
Actual Results:  
Nothing happens.

Expected Results:  
KDM should have returned to the graphical login mode (twice, in fact).

The issue seems to be caused by the use of the monotonic clock, introduced by the commit [1], fixing bug #269522. As it is just an "uptime", it totally breaks the timeout calculation logic in /kdm/backend/dm.c.
See line 493:
---------- >8 ----------
utp->time = ut->ut_time;
---------- 8< ----------
Assigning ut->ut_time, which is a real clock time, to utp->time, which is a monotonic clock time, seems to be a bad idea.
Later it is being compared to now, which is a monotonic clock time:
---------- >8 ----------
ends = utp->time + (utp->hadSess ? TIME_RELOG : TIME_LOG);
if (ends <= now) {
---------- 8< ----------
- so a console login is only timed out, when "uptime" reaches current real clock time.
To confirm the guess, I set the system time to the monotonic clock time, blanked the utmp database and restarted KDM, and after that the issue went away.

[1] http://commits.kde.org/kde-workspace/9550608407aa72e77919a9ad1182f65cff0198cb
Comment 1 Oswald Buddenhagen 2013-02-10 16:51:32 UTC
thanks for the excellent report.
i'm not sure how to fix this. the easiest is just keeping a delta between the monotonic and the wall clock and applying it to ut_time. of course this is subject to the time jump problem which using the monotonic clock addresses in the first place. though i guess the worst that can happen is that we immediately return to the graphical login (provided we cap underflow and times in the future).
Comment 2 Алексей Шилин 2013-02-25 18:35:47 UTC
(In reply to comment #1)
> i'm not sure how to fix this. the easiest is just keeping a delta between
> the monotonic and the wall clock and applying it to ut_time. of course this
> is subject to the time jump problem which using the monotonic clock
> addresses in the first place. though i guess the worst that can happen is
> that we immediately return to the graphical login (provided we cap underflow
> and times in the future).

I don't think, that there is a way to fix the time jump problem completely, while the utmp database keeps using a real clock time, and these timestamps are being used to calculate timeouts.
Simply applying delta won't fix it too. Here is a possible scenario.
1. A user logs out.
2. A timestamp is being written to the utmp database.
3. The real clock time changes to the past. The timestamp is in the future now.
4. KDM calculates new (smaller) delta and applies it to the old (before time change) utmp timestamp.
There is, however, a possible solution, although not ideal: if ut->ut_time > now, then use current now value instead of the timestamp. This change will make console login timeouts a bit volatile, but will limit the consequences of the bug a lot.
However, it will require a way to save state to prevent assigning a new now value every time. This can be implemented with an array of structs like { time_t ut_time, used_time; }, bijectively mapped to consoleTTYs values, like shown below.
---------- >8 ----------
if (ut->ut_time != $struct.ut_time) {
  $struct.ut_time = ut->ut_time;
  $struct.used_time =  ut->ut_time - delta > now ? now : ut->ut_time - delta;
}
utp->time = $struct.used_time;
---------- 8< ----------
Comment 3 Oswald Buddenhagen 2014-03-28 17:06:56 UTC
Git commit 3b3f247f28b25e61a9d1820ea25f3c4a2b699a1d by Oswald Buddenhagen.
Committed on 28/03/2014 at 16:52.
Pushed by ossi into branch 'KDE/4.11'.

fix resumption from console mode when monotonic clock is in use
FIXED-IN: 4.11.8

M  +14   -3    kdm/backend/dm.c
M  +7    -3    kdm/backend/dm.h

http://commits.kde.org/kde-workspace/3b3f247f28b25e61a9d1820ea25f3c4a2b699a1d