]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | \r |
2 | /* Support for dynamic loading of extension modules */\r | |
3 | \r | |
4 | #include <kernel/image.h>\r | |
5 | #include <kernel/OS.h>\r | |
6 | #include <stdlib.h>\r | |
7 | \r | |
8 | #include "Python.h"\r | |
9 | #include "importdl.h"\r | |
10 | \r | |
11 | const struct filedescr _PyImport_DynLoadFiletab[] = {\r | |
12 | {".so", "rb", C_EXTENSION},\r | |
13 | {"module.so", "rb", C_EXTENSION},\r | |
14 | {0, 0}\r | |
15 | };\r | |
16 | \r | |
17 | #if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)\r | |
18 | #undef MAXPATHLEN\r | |
19 | #endif\r | |
20 | \r | |
21 | #ifdef WITH_THREAD\r | |
22 | #include "pythread.h"\r | |
23 | static PyThread_type_lock beos_dyn_lock;\r | |
24 | #endif\r | |
25 | \r | |
26 | static PyObject *beos_dyn_images = NULL;\r | |
27 | \r | |
28 | /* ----------------------------------------------------------------------\r | |
29 | * BeOS dynamic loading support\r | |
30 | *\r | |
31 | * This uses shared libraries, but BeOS has its own way of doing things\r | |
32 | * (much easier than dlfnc.h, from the look of things). We'll use a\r | |
33 | * Python Dictionary object to store the images_ids so we can be very\r | |
34 | * nice and unload them when we exit.\r | |
35 | *\r | |
36 | * Note that this is thread-safe. Probably irrelevent, because of losing\r | |
37 | * systems... Python probably disables threads while loading modules.\r | |
38 | * Note the use of "probably"! Better to be safe than sorry. [chrish]\r | |
39 | *\r | |
40 | * As of 1.5.1 this should also work properly when you've configured\r | |
41 | * Python without thread support; the 1.5 version required it, which wasn't\r | |
42 | * very friendly. Note that I haven't tested it without threading... why\r | |
43 | * would you want to avoid threads on BeOS? [chrish]\r | |
44 | *\r | |
45 | * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn\r | |
46 | * tells me it's not necessary anymore because of PyCObject_Import().\r | |
47 | * [chrish]\r | |
48 | */\r | |
49 | \r | |
50 | /* Whack an item; the item is an image_id in disguise, so we'll call\r | |
51 | * unload_add_on() for it.\r | |
52 | */\r | |
53 | static void beos_nuke_dyn( PyObject *item )\r | |
54 | {\r | |
55 | status_t retval;\r | |
56 | \r | |
57 | if( item ) {\r | |
58 | image_id id = (image_id)PyInt_AsLong( item );\r | |
59 | \r | |
60 | retval = unload_add_on( id );\r | |
61 | }\r | |
62 | }\r | |
63 | \r | |
64 | /* atexit() handler that'll call unload_add_on() for every item in the\r | |
65 | * dictionary.\r | |
66 | */\r | |
67 | static void beos_cleanup_dyn( void )\r | |
68 | {\r | |
69 | if( beos_dyn_images ) {\r | |
70 | int idx;\r | |
71 | int list_size;\r | |
72 | PyObject *id_list;\r | |
73 | \r | |
74 | #ifdef WITH_THREAD\r | |
75 | PyThread_acquire_lock( beos_dyn_lock, 1 );\r | |
76 | #endif\r | |
77 | \r | |
78 | id_list = PyDict_Values( beos_dyn_images );\r | |
79 | \r | |
80 | list_size = PyList_Size( id_list );\r | |
81 | for( idx = 0; idx < list_size; idx++ ) {\r | |
82 | PyObject *the_item;\r | |
83 | \r | |
84 | the_item = PyList_GetItem( id_list, idx );\r | |
85 | beos_nuke_dyn( the_item );\r | |
86 | }\r | |
87 | \r | |
88 | PyDict_Clear( beos_dyn_images );\r | |
89 | \r | |
90 | #ifdef WITH_THREAD\r | |
91 | PyThread_free_lock( beos_dyn_lock );\r | |
92 | #endif\r | |
93 | }\r | |
94 | }\r | |
95 | \r | |
96 | /*\r | |
97 | * Initialize our dictionary, and the dictionary mutex.\r | |
98 | */\r | |
99 | static void beos_init_dyn( void )\r | |
100 | {\r | |
101 | /* We're protected from a race condition here by the atomic init_count\r | |
102 | * variable.\r | |
103 | */\r | |
104 | static int32 init_count = 0;\r | |
105 | int32 val;\r | |
106 | \r | |
107 | val = atomic_add( &init_count, 1 );\r | |
108 | if( beos_dyn_images == NULL && val == 0 ) {\r | |
109 | beos_dyn_images = PyDict_New();\r | |
110 | #ifdef WITH_THREAD\r | |
111 | beos_dyn_lock = PyThread_allocate_lock();\r | |
112 | #endif\r | |
113 | atexit( beos_cleanup_dyn );\r | |
114 | }\r | |
115 | }\r | |
116 | \r | |
117 | /*\r | |
118 | * Add an image_id to the dictionary; the module name of the loaded image\r | |
119 | * is the key. Note that if the key is already in the dict, we unload\r | |
120 | * that image; this should allow reload() to work on dynamically loaded\r | |
121 | * modules (super-keen!).\r | |
122 | */\r | |
123 | static void beos_add_dyn( char *name, image_id id )\r | |
124 | {\r | |
125 | int retval;\r | |
126 | PyObject *py_id;\r | |
127 | \r | |
128 | if( beos_dyn_images == NULL ) {\r | |
129 | beos_init_dyn();\r | |
130 | }\r | |
131 | \r | |
132 | #ifdef WITH_THREAD\r | |
133 | retval = PyThread_acquire_lock( beos_dyn_lock, 1 );\r | |
134 | #endif\r | |
135 | \r | |
136 | /* If there's already an object with this key in the dictionary,\r | |
137 | * we're doing a reload(), so let's nuke it.\r | |
138 | */\r | |
139 | py_id = PyDict_GetItemString( beos_dyn_images, name );\r | |
140 | if( py_id ) {\r | |
141 | beos_nuke_dyn( py_id );\r | |
142 | retval = PyDict_DelItemString( beos_dyn_images, name );\r | |
143 | }\r | |
144 | \r | |
145 | py_id = PyInt_FromLong( (long)id );\r | |
146 | if( py_id ) {\r | |
147 | retval = PyDict_SetItemString( beos_dyn_images, name, py_id );\r | |
148 | }\r | |
149 | \r | |
150 | #ifdef WITH_THREAD\r | |
151 | PyThread_release_lock( beos_dyn_lock );\r | |
152 | #endif\r | |
153 | }\r | |
154 | \r | |
155 | \r | |
156 | \r | |
157 | dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,\r | |
158 | const char *pathname, FILE *fp)\r | |
159 | {\r | |
160 | dl_funcptr p;\r | |
161 | image_id the_id;\r | |
162 | status_t retval;\r | |
163 | char fullpath[PATH_MAX];\r | |
164 | char funcname[258];\r | |
165 | \r | |
166 | if( Py_VerboseFlag ) {\r | |
167 | printf( "load_add_on( %s )\n", pathname );\r | |
168 | }\r | |
169 | \r | |
170 | /* Hmm, this old bug appears to have regenerated itself; if the\r | |
171 | * path isn't absolute, load_add_on() will fail. Reported to Be\r | |
172 | * April 21, 1998.\r | |
173 | */\r | |
174 | if( pathname[0] != '/' ) {\r | |
175 | (void)getcwd( fullpath, PATH_MAX );\r | |
176 | (void)strncat( fullpath, "/", PATH_MAX );\r | |
177 | (void)strncat( fullpath, pathname, PATH_MAX );\r | |
178 | \r | |
179 | if( Py_VerboseFlag ) {\r | |
180 | printf( "load_add_on( %s )\n", fullpath );\r | |
181 | }\r | |
182 | } else {\r | |
183 | (void)strcpy( fullpath, pathname );\r | |
184 | }\r | |
185 | \r | |
186 | the_id = load_add_on( fullpath );\r | |
187 | if( the_id < B_NO_ERROR ) {\r | |
188 | /* It's too bad load_add_on() doesn't set errno or something...\r | |
189 | */\r | |
190 | char buff[256]; /* hate hard-coded string sizes... */\r | |
191 | \r | |
192 | if( Py_VerboseFlag ) {\r | |
193 | printf( "load_add_on( %s ) failed", fullpath );\r | |
194 | }\r | |
195 | \r | |
196 | if( the_id == B_ERROR )\r | |
197 | PyOS_snprintf( buff, sizeof(buff),\r | |
198 | "BeOS: Failed to load %.200s",\r | |
199 | fullpath );\r | |
200 | else\r | |
201 | PyOS_snprintf( buff, sizeof(buff),\r | |
202 | "Unknown error loading %.200s",\r | |
203 | fullpath );\r | |
204 | \r | |
205 | PyErr_SetString( PyExc_ImportError, buff );\r | |
206 | return NULL;\r | |
207 | }\r | |
208 | \r | |
209 | PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);\r | |
210 | if( Py_VerboseFlag ) {\r | |
211 | printf( "get_image_symbol( %s )\n", funcname );\r | |
212 | }\r | |
213 | \r | |
214 | retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );\r | |
215 | if( retval != B_NO_ERROR || p == NULL ) {\r | |
216 | /* That's bad, we can't find that symbol in the module...\r | |
217 | */\r | |
218 | char buff[256]; /* hate hard-coded string sizes... */\r | |
219 | \r | |
220 | if( Py_VerboseFlag ) {\r | |
221 | printf( "get_image_symbol( %s ) failed", funcname );\r | |
222 | }\r | |
223 | \r | |
224 | switch( retval ) {\r | |
225 | case B_BAD_IMAGE_ID:\r | |
226 | PyOS_snprintf( buff, sizeof(buff),\r | |
227 | "can't load init function for dynamic module: "\r | |
228 | "Invalid image ID for %.180s", fullpath );\r | |
229 | break;\r | |
230 | case B_BAD_INDEX:\r | |
231 | PyOS_snprintf( buff, sizeof(buff),\r | |
232 | "can't load init function for dynamic module: "\r | |
233 | "Bad index for %.180s", funcname );\r | |
234 | break;\r | |
235 | default:\r | |
236 | PyOS_snprintf( buff, sizeof(buff),\r | |
237 | "can't load init function for dynamic module: "\r | |
238 | "Unknown error looking up %.180s", funcname );\r | |
239 | break;\r | |
240 | }\r | |
241 | \r | |
242 | retval = unload_add_on( the_id );\r | |
243 | \r | |
244 | PyErr_SetString( PyExc_ImportError, buff );\r | |
245 | return NULL;\r | |
246 | }\r | |
247 | \r | |
248 | /* Save the module name and image ID for later so we can clean up\r | |
249 | * gracefully.\r | |
250 | */\r | |
251 | beos_add_dyn( fqname, the_id );\r | |
252 | \r | |
253 | return p;\r | |
254 | }\r |