Workaround: Pending signal making wait_event_interruptible() return prematurely

This post was written by eli on May 8, 2011
Posted Under: Linux kernel

It all starts with this: I’m not ready to return from my character device’s release() method before I know that the underlying hardware has acknowledged the shutdown. It is actually expected to do so quickly, so I relied on a wait_event_interruptible() call within the release method to do the short wait for the acknowledge.

And it actually worked well, until specific cases where I hit CTRL-C while a read() was blocking. I’m not exactly sure of why, but if the signal arrived while a blocking on wait_event_interruptible() within read(), the signal wouldn’t be cleared, so release() was called with the signal pending. As was quite evident with this little snippet in the release() code.

if (signal_pending(current))
  printk(KERN_WARNING "Signal is pending on release()...\n");

… which ended up with the wait_event_interruptible() in the release() method returning immediately, yelling that the hardware didn’t respond.

Blocking indefinitely is out of the question, so the simple workaround is to sleep another 100ms if wait_event_interruptible() returns prematurely, and then check if the hardware is done. That should be far more than needed for the hardware, and a fairly small time penalty for the user.

So the waiting part in release() now goes:

if (wait_event_interruptible(fstr->wait, (!fstr->flag)))
  msleep(100);

The cute trick here is that the sleep takes place only in the event of an interrupt, so in a normal release() call we quit much faster.

Add a Comment

required, use real name
required, will not be published
optional, your blog address