From: fredrik Date: Tue, 30 Jan 2007 02:24:29 +0000 (+0000) Subject: Fix some potential issues when freeing running cbchains. X-Git-Tag: 0.3~92 X-Git-Url: http://dolda2000.com/gitweb/?p=doldaconnect.git;a=commitdiff_plain;h=049aedb6ec90e163d2e0cc51ab66f65d18700a86 Fix some potential issues when freeing running cbchains. git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/doldaconnect@838 959494ce-11ee-0310-bf91-de5d638817bd --- diff --git a/include/utils.h b/include/utils.h index 5c50dd4..4eada80 100644 --- a/include/utils.h +++ b/include/utils.h @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef DAEMON #include "log.h" #endif @@ -54,6 +55,7 @@ struct cbchain_ ## name { \ int (*func)(args, void *data); \ void (*destroy)(void *data); \ void *data; \ + int running, free; \ } * name #define GCBCHAIN(name, args...) \ @@ -129,6 +131,7 @@ do { \ do { \ struct cbchain_ ## name *__new_cb__; \ __new_cb__ = smalloc(sizeof(*__new_cb__)); \ + __new_cb__->running = __new_cb__->free = 0; \ __new_cb__->func = funca; \ __new_cb__->destroy = destroya; \ __new_cb__->data = dataa; \ @@ -140,11 +143,12 @@ do { \ (obj)->name = __new_cb__; \ } while(0) -#define CBUNREG(obj, name, dataa) \ -do { \ +#define CBUNREG(obj, name, funca, dataa) \ +({ \ struct cbchain_ ## name *__cur__; \ + int __found__ = 0; \ for(__cur__ = (obj)->name; __cur__ != NULL; __cur__ = __cur__->next) { \ - if(__cur__->data == (dataa)) { \ + if(((void *)(__cur__->func) == (void *)(funca)) && (__cur__->data == (void *)(dataa))) { \ if(__cur__->destroy != NULL) \ __cur__->destroy(__cur__->data); \ if(__cur__->prev != NULL) \ @@ -154,10 +158,11 @@ do { \ if(__cur__ == (obj)->name) \ (obj)->name = __cur__->next; \ free(__cur__); \ + __found__ = 1; \ break; \ } \ } \ -} while(0) +__found__;}) #define GCBREG(name, funca, dataa) \ do { \ @@ -180,18 +185,30 @@ do { \ struct cbchain_ ## name *__cur__; \ while((__cur__ = (obj)->name) != NULL) { \ (obj)->name = __cur__->next; \ - if(__cur__->destroy != NULL) \ - __cur__->destroy(__cur__->data); \ - free(__cur__); \ + if(__cur__->running) { \ + __cur__->free = 1; \ + } else { \ + if(__cur__->destroy != NULL) \ + __cur__->destroy(__cur__->data); \ + free(__cur__); \ + } \ } \ } while(0) #define CBCHAINDOCB(obj, name, args...) \ do { \ struct cbchain_ ## name *__cur__, *__next__; \ + int __res__; \ for(__cur__ = (obj)->name; __cur__ != NULL; __cur__ = __next__) { \ __next__ = __cur__->next; \ - if(__cur__->func(args, __cur__->data)) { \ + __cur__->running = 1; \ + __res__ = __cur__->func(args, __cur__->data); \ + __cur__->running = 0; \ + if(__cur__->free) { \ + free(__cur__); \ + break; \ + } \ + if(__res__) { \ if(__cur__->next != NULL) \ __cur__->next->prev = __cur__->prev; \ if(__cur__->prev != NULL) \