blob: 4b4a49a57da964044fbc5e917d9a15c17330fa01 [file] [log] [blame]
Guido van Rossum22a1d361999-12-20 21:18:49 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* Support for dynamic loading of extension modules */
33
34#include <kernel/image.h>
35#include <kernel/OS.h>
36#include <stdlib.h>
37#include <unistd.h>
38
39#include "Python.h"
40#include "importdl.h"
41
42const struct filedescr _PyImport_DynLoadFiletab[] = {
43 {".so", "rb", C_EXTENSION},
44 {"module.so", "rb", C_EXTENSION},
45 {0, 0}
46};
47
48#if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
49#undef MAXPATHLEN
50#endif
51
52#ifdef WITH_THREAD
53#include "pythread.h"
54static PyThread_type_lock beos_dyn_lock;
55#endif
56
57static PyObject *beos_dyn_images = NULL;
58
59/* ----------------------------------------------------------------------
60 * BeOS dynamic loading support
61 *
62 * This uses shared libraries, but BeOS has its own way of doing things
63 * (much easier than dlfnc.h, from the look of things). We'll use a
64 * Python Dictionary object to store the images_ids so we can be very
65 * nice and unload them when we exit.
66 *
67 * Note that this is thread-safe. Probably irrelevent, because of losing
68 * systems... Python probably disables threads while loading modules.
69 * Note the use of "probably"! Better to be safe than sorry. [chrish]
70 *
71 * As of 1.5.1 this should also work properly when you've configured
72 * Python without thread support; the 1.5 version required it, which wasn't
73 * very friendly. Note that I haven't tested it without threading... why
74 * would you want to avoid threads on BeOS? [chrish]
75 *
76 * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn
77 * tells me it's not necessary anymore because of PyCObject_Import().
78 * [chrish]
79 */
80
81/* Whack an item; the item is an image_id in disguise, so we'll call
82 * unload_add_on() for it.
83 */
84static void beos_nuke_dyn( PyObject *item )
85{
86 status_t retval;
87
88 if( item ) {
89 image_id id = (image_id)PyInt_AsLong( item );
90
91 retval = unload_add_on( id );
92 }
93}
94
95/* atexit() handler that'll call unload_add_on() for every item in the
96 * dictionary.
97 */
98static void beos_cleanup_dyn( void )
99{
100 if( beos_dyn_images ) {
101 int idx;
102 int list_size;
103 PyObject *id_list;
104
105#ifdef WITH_THREAD
106 PyThread_acquire_lock( beos_dyn_lock, 1 );
107#endif
108
109 id_list = PyDict_Values( beos_dyn_images );
110
111 list_size = PyList_Size( id_list );
112 for( idx = 0; idx < list_size; idx++ ) {
113 PyObject *the_item;
114
115 the_item = PyList_GetItem( id_list, idx );
116 beos_nuke_dyn( the_item );
117 }
118
119 PyDict_Clear( beos_dyn_images );
120
121#ifdef WITH_THREAD
122 PyThread_free_lock( beos_dyn_lock );
123#endif
124 }
125}
126
127/*
128 * Initialize our dictionary, and the dictionary mutex.
129 */
130static void beos_init_dyn( void )
131{
132 /* We're protected from a race condition here by the atomic init_count
133 * variable.
134 */
135 static int32 init_count = 0;
136 int32 val;
137
138 val = atomic_add( &init_count, 1 );
139 if( beos_dyn_images == NULL && val == 0 ) {
140 beos_dyn_images = PyDict_New();
141#ifdef WITH_THREAD
142 beos_dyn_lock = PyThread_allocate_lock();
143#endif
144 atexit( beos_cleanup_dyn );
145 }
146}
147
148/*
149 * Add an image_id to the dictionary; the module name of the loaded image
150 * is the key. Note that if the key is already in the dict, we unload
151 * that image; this should allow reload() to work on dynamically loaded
152 * modules (super-keen!).
153 */
154static void beos_add_dyn( char *name, image_id id )
155{
156 int retval;
157 PyObject *py_id;
158
159 if( beos_dyn_images == NULL ) {
160 beos_init_dyn();
161 }
162
163#ifdef WITH_THREAD
164 retval = PyThread_acquire_lock( beos_dyn_lock, 1 );
165#endif
166
167 /* If there's already an object with this key in the dictionary,
168 * we're doing a reload(), so let's nuke it.
169 */
170 py_id = PyDict_GetItemString( beos_dyn_images, name );
171 if( py_id ) {
172 beos_nuke_dyn( py_id );
173 retval = PyDict_DelItemString( beos_dyn_images, name );
174 }
175
176 py_id = PyInt_FromLong( (long)id );
177 if( py_id ) {
178 retval = PyDict_SetItemString( beos_dyn_images, name, py_id );
179 }
180
181#ifdef WITH_THREAD
182 PyThread_release_lock( beos_dyn_lock );
183#endif
184}
185
186
187
188dl_funcptr _PyImport_GetDynLoadFunc(const char *name, const char *funcname,
189 const char *pathname, FILE *fp)
190{
191 dl_funcptr p;
192 image_id the_id;
193 status_t retval;
194 char fullpath[PATH_MAX];
195
196 if( Py_VerboseFlag ) {
197 printf( "load_add_on( %s )\n", pathname );
198 }
199
200 /* Hmm, this old bug appears to have regenerated itself; if the
201 * path isn't absolute, load_add_on() will fail. Reported to Be
202 * April 21, 1998.
203 */
204 if( pathname[0] != '/' ) {
205 (void)getcwd( fullpath, PATH_MAX );
206 (void)strncat( fullpath, "/", PATH_MAX );
207 (void)strncat( fullpath, pathname, PATH_MAX );
208
209 if( Py_VerboseFlag ) {
210 printf( "load_add_on( %s )\n", fullpath );
211 }
212 } else {
213 (void)strcpy( fullpath, pathname );
214 }
215
216 the_id = load_add_on( fullpath );
217 if( the_id < B_NO_ERROR ) {
218 /* It's too bad load_add_on() doesn't set errno or something...
219 */
220 char buff[256]; /* hate hard-coded string sizes... */
221
222 if( Py_VerboseFlag ) {
223 printf( "load_add_on( %s ) failed", fullpath );
224 }
225
226 switch( the_id ) {
227 case B_ERROR:
228 sprintf( buff, "BeOS: Failed to load %.200s", fullpath );
229 break;
230 default:
231 sprintf( buff, "Unknown error loading %.200s", fullpath );
232 break;
233 }
234
235 PyErr_SetString( PyExc_ImportError, buff );
236 return NULL;
237 }
238
239 if( Py_VerboseFlag ) {
240 printf( "get_image_symbol( %s )\n", funcname );
241 }
242
243 retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
244 if( retval != B_NO_ERROR || p == NULL ) {
245 /* That's bad, we can't find that symbol in the module...
246 */
247 char buff[256]; /* hate hard-coded string sizes... */
248
249 if( Py_VerboseFlag ) {
250 printf( "get_image_symbol( %s ) failed", funcname );
251 }
252
253 switch( retval ) {
254 case B_BAD_IMAGE_ID:
255 sprintf( buff, "can't load init function for dynamic module: "
256 "Invalid image ID for %.180s", fullpath );
257 break;
258 case B_BAD_INDEX:
259 sprintf( buff, "can't load init function for dynamic module: "
260 "Bad index for %.180s", funcname );
261 break;
262 default:
263 sprintf( buff, "can't load init function for dynamic module: "
264 "Unknown error looking up %.180s", funcname );
265 break;
266 }
267
268 retval = unload_add_on( the_id );
269
270 PyErr_SetString( PyExc_ImportError, buff );
271 return NULL;
272 }
273
274 /* Save the module name and image ID for later so we can clean up
275 * gracefully.
276 */
277 beos_add_dyn( name, the_id );
278
279 return p;
280}