lkml.org 
[lkml]   [2003]   [Mar]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: [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:0.036 / U:0.288 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site