Fix some potential issues when freeing running cbchains.
authorfredrik <fredrik@959494ce-11ee-0310-bf91-de5d638817bd>
Tue, 30 Jan 2007 02:24:29 +0000 (02:24 +0000)
committerfredrik <fredrik@959494ce-11ee-0310-bf91-de5d638817bd>
Tue, 30 Jan 2007 02:24:29 +0000 (02:24 +0000)
git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/doldaconnect@838 959494ce-11ee-0310-bf91-de5d638817bd

include/utils.h

index 5c50dd4..4eada80 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <malloc.h>
+#include <assert.h>
 #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) \