$NetBSD: patch-ak,v 1.3 2010/04/23 14:08:17 he Exp $ Prevent problem exposed by "library cloning", where the dlopen()-returned handle is copied, causing dlclose() to be called twice with the same handle, which in turn triggers a warning from ld.elf_so on NetBSD. Ref. http://trac.parrot.org/parrot/ticket/1340. --- config/gen/platform/generic/dl.c.orig 2010-03-22 13:39:23.000000000 +0100 +++ config/gen/platform/generic/dl.c @@ -22,11 +22,69 @@ Dynlib stuff */ #ifdef PARROT_HAS_HEADER_DLFCN +# include +# include # include #endif #define PARROT_DLOPEN_FLAGS RTLD_LAZY + +#ifdef PARROT_HAS_HEADER_DLFCN + +struct handle_entry { + void *handle; + struct handle_entry *next; +}; + +struct handle_entry *handle_list = NULL; + +static void +push_handle_entry(void *handle) +{ + struct handle_entry *e; + + e = (struct handle_entry *) malloc(sizeof(struct handle_entry)); + if (!e) { return; } + e->handle = handle; + e->next = handle_list; + handle_list = e; +} + +static void * +find_handle_entry(void *handle) +{ + struct handle_entry *e; + + for(e = handle_list; e; e = e->next) { + if (e->handle == handle) + return handle; + } + return NULL; +} + +static void +remove_handle_entry(void *handle) +{ + struct handle_entry *cur, *prev, *p; + + if (handle_list) { + if (handle_list->handle == handle) { + p = handle_list; + handle_list = p->next; + free(p); + } else { + for (cur = handle_list; cur; prev = cur, cur = cur->next) { + if (cur->handle == handle) { + prev->next = cur->next; + free(cur); + } + } + } + } +} +#endif /* PARROT_HAS_HEADER_DLFCN */ + /* =item C @@ -39,8 +97,12 @@ void * Parrot_dlopen(const char *filename, Parrot_dlopen_flags flags) { #ifdef PARROT_HAS_HEADER_DLFCN - return dlopen(filename, PARROT_DLOPEN_FLAGS - | ((flags & Parrot_dlopen_global_FLAG) ? RTLD_GLOBAL : 0)); + void *h; + + h = dlopen(filename, PARROT_DLOPEN_FLAGS + | ((flags & Parrot_dlopen_global_FLAG) ? RTLD_GLOBAL : 0)); + push_handle_entry(h); + return h; #else return 0; #endif @@ -94,10 +156,15 @@ int Parrot_dlclose(void *handle) { #ifdef PARROT_HAS_HEADER_DLFCN - return dlclose(handle); -#else - return -1; + int rv; + + if (find_handle_entry(handle)) { + remove_handle_entry(handle); + rv = dlclose(handle); + return rv; + } #endif + return -1; } /*