blob: 717d5a9510a85a2f945f8dfd2859e708b58abbb5 [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
Guido van Rossum96a8fb71999-12-22 14:09:35 +0000188dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
Guido van Rossum22a1d361999-12-20 21:18:49 +0000189 const char *pathname, FILE *fp)
190{
191 dl_funcptr p;
192 image_id the_id;
193 status_t retval;
194 char fullpath[PATH_MAX];
Guido van Rossum96a8fb71999-12-22 14:09:35 +0000195 char funcname[258];
Guido van Rossum22a1d361999-12-20 21:18:49 +0000196
197 if( Py_VerboseFlag ) {
198 printf( "load_add_on( %s )\n", pathname );
199 }
200
201 /* Hmm, this old bug appears to have regenerated itself; if the
202 * path isn't absolute, load_add_on() will fail. Reported to Be
203 * April 21, 1998.
204 */
205 if( pathname[0] != '/' ) {
206 (void)getcwd( fullpath, PATH_MAX );
207 (void)strncat( fullpath, "/", PATH_MAX );
208 (void)strncat( fullpath, pathname, PATH_MAX );
209
210 if( Py_VerboseFlag ) {
211 printf( "load_add_on( %s )\n", fullpath );
212 }
213 } else {
214 (void)strcpy( fullpath, pathname );
215 }
216
217 the_id = load_add_on( fullpath );
218 if( the_id < B_NO_ERROR ) {
219 /* It's too bad load_add_on() doesn't set errno or something...
220 */
221 char buff[256]; /* hate hard-coded string sizes... */
222
223 if( Py_VerboseFlag ) {
224 printf( "load_add_on( %s ) failed", fullpath );
225 }
226
227 switch( the_id ) {
228 case B_ERROR:
229 sprintf( buff, "BeOS: Failed to load %.200s", fullpath );
230 break;
231 default:
232 sprintf( buff, "Unknown error loading %.200s", fullpath );
233 break;
234 }
235
236 PyErr_SetString( PyExc_ImportError, buff );
237 return NULL;
238 }
239
Guido van Rossum96a8fb71999-12-22 14:09:35 +0000240 sprintf(funcname, "init%.200s", shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +0000241 if( Py_VerboseFlag ) {
242 printf( "get_image_symbol( %s )\n", funcname );
243 }
244
245 retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
246 if( retval != B_NO_ERROR || p == NULL ) {
247 /* That's bad, we can't find that symbol in the module...
248 */
249 char buff[256]; /* hate hard-coded string sizes... */
250
251 if( Py_VerboseFlag ) {
252 printf( "get_image_symbol( %s ) failed", funcname );
253 }
254
255 switch( retval ) {
256 case B_BAD_IMAGE_ID:
257 sprintf( buff, "can't load init function for dynamic module: "
258 "Invalid image ID for %.180s", fullpath );
259 break;
260 case B_BAD_INDEX:
261 sprintf( buff, "can't load init function for dynamic module: "
262 "Bad index for %.180s", funcname );
263 break;
264 default:
265 sprintf( buff, "can't load init function for dynamic module: "
266 "Unknown error looking up %.180s", funcname );
267 break;
268 }
269
270 retval = unload_add_on( the_id );
271
272 PyErr_SetString( PyExc_ImportError, buff );
273 return NULL;
274 }
275
276 /* Save the module name and image ID for later so we can clean up
277 * gracefully.
278 */
Guido van Rossum96a8fb71999-12-22 14:09:35 +0000279 beos_add_dyn( fqname, the_id );
Guido van Rossum22a1d361999-12-20 21:18:49 +0000280
281 return p;
282}