redmine

[kqueue] Fixed segfault

Tester: Artyom A Anikeev <anikeev@ut.mephi.ru>
... ... @@ -114,6 +114,7 @@ int kqueue_init(ctx_t *_ctx_p) {
static int monobj_filecmp(const void *_a, const void *_b) {
const monobj_t *a=_a, *b=_b;
debug(95, "a == %p; b == %p", a, b);
int diff_inode = a->inode - b->inode;
debug(90, "diff_inode = %i", diff_inode);
... ... @@ -203,6 +204,7 @@ void child_free(monobj_t *node) {
critical_on (kqueue_unmark(ctx_p, node));
}
int kqueue_unmark(ctx_t *ctx_p, monobj_t *obj_p) {
monobj_t *parent;
debug(20, "obj_p == %p", obj_p);
struct kqueue_data *dat = ctx_p->fsmondata;
#ifdef VERYPARANOID
... ... @@ -212,13 +214,23 @@ int kqueue_unmark(ctx_t *ctx_p, monobj_t *obj_p) {
}
#endif
if (obj_p->changelist_id+1 < dat->changelist_used)
if (obj_p->changelist_id+1 < dat->changelist_used) {
debug(20, "dat->changelist: moving %i -> %i", dat->changelist_used, obj_p->changelist_id);
memcpy(&dat->changelist[obj_p->changelist_id], &dat->changelist[dat->changelist_used], sizeof(*dat->changelist));
}
dat->changelist_used--;
close(obj_p->fd);
parent = obj_p->parent;
if (parent != NULL) {
debug(20, "Removing the obj from parent->children_tree (obj_p == %p; parent->children_tree == %p)", obj_p, parent->children_tree);
tdump(parent->children_tree);
tdelete(obj_p, &parent->children_tree, monobj_filecmp);
}
debug(20, "Removing the obj itself");
tdestroy(obj_p->children_tree, (void (*)(void *))child_free);
tdelete(obj_p, &dat->file_btree, monobj_filecmp);
tdelete(obj_p, &dat->fd_btree, monobj_fdcmp);
... ... @@ -253,6 +265,7 @@ monobj_t *kqueue_start_watch(ctx_t *ctx_p, ino_t inode, dev_t device, int dir_fd
debug(20, "Adding a child for dir_fd == %i", dir_fd);
if (tsearch((void *)obj_p, &parent->children_tree, monobj_filecmp) == NULL)
critical("Not enough memory");
tdump(parent->children_tree);
debug(25, "parent->children_tree == %p", parent->children_tree);
}
... ... @@ -672,7 +685,7 @@ int kqueue_handle(ctx_t *ctx_p, indexes_t *indexes_p) {
obj.fd = ev_p->ident;
monobj_t **obj_pp = tfind((void *)&obj, &dat->fd_btree, monobj_fdcmp);
if (obj_pp == NULL) {
error("Internal error. Cannot find internal structure for fd == %u. Skipping the event.", ev_p->ident);
debug(3, "Cannot find internal structure for fd == %u. Skipping the event.", ev_p->ident);
continue;
}
monobj_t *obj_p = *obj_pp;
... ...
... ... @@ -21,24 +21,48 @@
#include "port-hacks.h"
#include <stdlib.h>
#include "error.h"
#ifdef tdestroy_UNDEFINED
struct _tdestroy_tree {
struct _tcallfunct_tree {
void *data;
struct _tdestroy_tree *left;
struct _tdestroy_tree *right;
struct _tcallfunct_tree *left;
struct _tcallfunct_tree *right;
};
void tdestroy(void *root, void (*free_node)(void *node_data)) {
struct _tdestroy_tree *node_p = root;
void tcallfunct(void *root, void (*funct)(struct _tcallfunct_tree *node_p, void *arg), void *arg) {
struct _tcallfunct_tree *node_p = root;
if (node_p == NULL)
return;
tdestroy(node_p->left , free_node);
tdestroy(node_p->right, free_node);
tcallfunct(node_p->left , funct, arg);
tcallfunct(node_p->right, funct, arg);
funct(node_p, arg);
return;
}
void tdump_node(struct _tcallfunct_tree *node_p, void *arg) {
debug(80, "node_p == %p; node_p->left == %p; node_p->right == %p; node_p->data == %p", node_p, node_p->left, node_p->right, node_p->data);
return;
}
free_node(node_p->data);
void _tdump(void *root) {
debug(20, "root = %p", root);
tcallfunct(root, tdump_node, NULL);
return;
}
void tdestroy_freenode(struct _tcallfunct_tree *node_p, void *_free_node_funct) {
void (*free_node_funct)(void *node_data) = _free_node_funct;
free_node_funct(node_p->data);
free(node_p);
return;
}
void tdestroy(void *root, void (*free_node)(void *node_data)) {
tcallfunct(root, tdestroy_freenode, free_node);
return;
}
#endif
... ...
... ... @@ -75,6 +75,8 @@
#endif
#ifdef tdestroy_UNDEFINED
#define tdump(root) {if(_DEBUG_FORCE) _tdump(root);}
void _tdump(void *root);
extern void tdestroy(void *root, void (*free_node)(void *nodep));
#endif
... ...