lkml.org 
[lkml]   [2003]   [Mar]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    SubjectRe: [OOPS][2.5.66bk3+] run_timer_softirq - IRQ Mishandlings
    Date
    Perhaps adding this to the kernel as a config option might be handy for
    people looking for not freed timers?

    Shawn.

    ----- Original Message -----
    From: "Andrew Morton" <akpm@digeo.com>
    To: "Shawn Starr" <spstarr@sh0n.net>
    Cc: <rml@tech9.net>; <linux-kernel@vger.kernel.org>
    Sent: Saturday, March 29, 2003 5:28 PM
    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/

    \
     
     \ /
      Last update: 2005-03-22 13:34    [W:2.588 / U:0.168 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site