Comment 2 for bug 1037565

Revision history for this message
Tixy (Jon Medhurst) (tixy) wrote :

This bug is caused by the Android patch called " Input: evdev - Add ioctl to block suspend while event queue is not empty."

This is broken because evdev_enable_suspend_block() has

 spin_lock_irq(&client->buffer_lock);
 wake_lock_init(&client->wake_lock, WAKE_LOCK_SUSPEND, client->name);
 [...]
 spin_unlock_irq(&client->buffer_lock);

which means that wake_lock_init() is called with interrupts disabled. However wake_lock_init() calls wakeup_source_add() which itself uses spinlocks like...

 spin_lock_irq(&events_lock);
 [...]
 spin_unlock_irq(&events_lock);

which assumes that it is called with interrupts enabled. As a consequence, the spin_unlock_irq() above unconditionally enables irqs which means the evdev code which called it is now holding the client->buffer_lock with interrupts enabled, opening up the opportunity for deadlock to occur if an interrupt happens for an event which then calls evdev_pass_event() and then waits on the same spinlock.