Recursive deadlock on die_lock

From: Keith Owens (kaos@ocs.com.au)
Date: Sat Oct 13 2001 - 23:25:52 EST


Typical die() code.

spinlock_t die_lock = SPIN_LOCK_UNLOCKED;

void die(const char * str, struct pt_regs * regs, long err)
{
        console_verbose();
        spin_lock_irq(&die_lock);
        bust_spinlocks(1);
        printk("%s: %04lx\n", str, err & 0xffff);
        show_registers(regs);
        bust_spinlocks(0);
        spin_unlock_irq(&die_lock);
        do_exit(SIGSEGV);
}

If show_registers() fails (which it does far too often on IA64) then
the system deadlocks trying to recursively obtain die_lock. Also
die_lock is never used outside die(), it should be proc local.
Suggested fix:

void die(const char * str, struct pt_regs * regs, long err)
{
        static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
        static int die_lock_owner = -1, die_lock_owner_depth = 0;

        if (die_lock_owner != smp_processor_id()) {
                console_verbose();
                spin_lock_irq(&die_lock);
                die_lock_owner = smp_processor_id();
                die_lock_owner_depth = 0;
                bust_spinlocks(1);
        }

        if (++die_lock_owner_depth < 3) {
                printk("%s: %04lx\n", str, err & 0xffff);
                show_registers(regs);
        }
        else
                printk(KERN_ERR "Recursive die() failure, registers suppressed\n");

        bust_spinlocks(0);
        die_lock_owner = -1;
        spin_unlock_irq(&die_lock);
        do_exit(SIGSEGV);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Oct 15 2001 - 21:00:52 EST