Messages in this thread Patch in this message | | | Date | Sat, 29 Mar 2003 14:28:35 -0800 | From | Andrew Morton <> | Subject | Re: [OOPS][2.5.66bk3+] run_timer_softirq - IRQ Mishandlings |
| |
"Shawn Starr" <spstarr@sh0n.net> wrote: > > How can I go about debugging this? How can I find the path causing the > problem? >
Someone did
kfree(foo);
insead of
del_timer_sync(&foo->timer); kfree(foo);
so you have a freed-but-pending timer.
This is a horrid bug. One way to find it would be to change cache_free_debugcheck() to walk the just-freed-up memory looking for an instance of TIMER_MAGIC. If that is found and timer_pending() is true then drop a backtrace and print out timer->function.
err.... Here you go, this may find it.
fs/open.c | 33 +++++++++++++++++++++++++++++++++ include/linux/timer.h | 3 ++- mm/slab.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-)
diff -puN include/linux/timer.h~freed-timer-finder include/linux/timer.h --- 25/include/linux/timer.h~freed-timer-finder 2003-03-29 14:10:15.000000000 -0800 +++ 25-akpm/include/linux/timer.h 2003-03-29 14:10:26.000000000 -0800 @@ -8,11 +8,12 @@ struct tvec_t_base_s; struct timer_list { + unsigned long magic; + struct list_head entry; unsigned long expires; spinlock_t lock; - unsigned long magic; void (*function)(unsigned long); unsigned long data; diff -puN mm/slab.c~freed-timer-finder mm/slab.c --- 25/mm/slab.c~freed-timer-finder 2003-03-29 14:10:30.000000000 -0800 +++ 25-akpm/mm/slab.c 2003-03-29 14:16:23.000000000 -0800 @@ -800,6 +800,35 @@ static void poison_obj(kmem_cache_t *cac *(unsigned char *)(addr+size-1) = POISON_END; } +static void timer_hunt(kmem_cache_t *cachep, void *addr) +{ + int size = cachep->objsize; + void *p; + + if (cachep->flags & SLAB_RED_ZONE) { + addr += BYTES_PER_WORD; + size -= 2*BYTES_PER_WORD; + } + if (cachep->flags & SLAB_STORE_USER) { + size -= BYTES_PER_WORD; + } + + for (p = addr; p < addr + size; p += sizeof(unsigned long)) { + unsigned long *laddr = p; + + if (*laddr == TIMER_MAGIC) { + struct timer_list *timer; + + timer = (struct timer_list *)laddr; + if (timer_pending(timer)) { + printk("free of pending timer at %p\n", timer); + printk("function=%p\n", timer->function); + dump_stack(); + } + } + } +} + static void *fprob(unsigned char* addr, unsigned int size) { unsigned char *end; @@ -1603,6 +1632,7 @@ static inline void *cache_free_debugchec else cachep->dtor(objp, cachep, 0); } + timer_hunt(cachep, objp); if (cachep->flags & SLAB_POISON) poison_obj(cachep, objp, POISON_AFTER); #endif diff -puN fs/open.c~freed-timer-finder fs/open.c --- 25/fs/open.c~freed-timer-finder 2003-03-29 14:17:32.000000000 -0800 +++ 25-akpm/fs/open.c 2003-03-29 14:21:20.000000000 -0800 @@ -793,11 +793,44 @@ void fd_install(unsigned int fd, struct write_unlock(&files->file_lock); } +#include <linux/timer.h> + +struct foo_thing { + int a; + struct timer_list t; + int b; +}; + +static void my_foo(unsigned long data) +{ + printk("the handler\n"); +} + +static void timer_thing(void) +{ + static int did_it; + struct foo_thing *f; + + if (did_it) + return; + did_it = 1; + + f = kmalloc(sizeof(*f), GFP_KERNEL); + init_timer(&f->t); + f->t.expires = jiffies + HZ; + f->t.function = my_foo; + add_timer(&f->t); + kfree(f); +} + asmlinkage long sys_open(const char * filename, int flags, int mode) { char * tmp; int fd, error; + if (current->uid == 9999) + timer_thing(); + #if BITS_PER_LONG != 32 flags |= O_LARGEFILE; #endif _
- 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/
| |