KDrive race conditions on suspend/resume
matt.hoosier at gmail.com
Thu Jun 14 12:38:37 PDT 2007
I'm using KDrive with just the basic framebuffer backend, and have
narrowed down a failure to redraw after a suspend cycle, to a race
condition in handling the virtual terminal-related signals delivered
by the kernel.
The sequence is this:
(1) Suspend is initiated
(2) The kernel VT subsystem delivers a signal to KDrive, requesting that
the virtual console be released
(3) Kernel stalls suspend until KDrive makes an ioctl's on the terminal
to switch it out of graphical mode
(4) Kernel immediately starts executing, and nothing from userspace ever
gets scheduled again before suspending. This means that X's main
event loop (in os/WaitFor.c) is just done processing the VT release
request, but hasn't yet made a select() call for the next iteration of
(5) System sleeps...
(6) Kernel resume code takes over, begins restoring things. Partway
along, it attempts to restore the VT. So another signal is delivered to
KDrive to restore the graphics.
(7) Async signal handler runs in KDrive (hw/kdrive/linux/linux.c,
LinuxVTRequest), setting a flag ("kdSwitchPending") for inspection on
the next time that select() returns in the main event loop.
(8) Since X isn't yet scheduled after the resume,
the main event loop hasn't even gotten around to doing select() yet. So
this flag is never consulted before WaitForSomething() (os/WaitFor.c)
goes to sleep blocking on input. The VT restoration is never processed.
One can make some crude hacks  (like checking the value of
kdSwitchPending just before going to sleep in the mainloop) that
minimize the chances of a race, but it's not entirely gone.
That hack doesn't seem to do anything for a similar failure to repaint
the display after resuming, when the kernel-level support for
framebuffer consoles is turned off. Any ideas there?
It seems like one more robust solution would be to have a private
little pipe used as a dummy input source. The reader's end of that
pipe could be put into the set of fd's handled by the the select(),
with the VT signal handler just dumping a byte into that pipe as
More information about the xorg