1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
$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 <stddef.h>
+# include <stdlib.h>
# include <dlfcn.h>
#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<void * Parrot_dlopen(const char *filename, Parrot_dlopen_flags flags)>
@@ -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;
}
/*
|