Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f0473d5

Browse files
committed
Patch #412229: Add functions sys.getdlopenflags and sys.setdlopenflags.
Add dlopenflags to PyInterpreterState, and use it in dlopen calls.
1 parent 984158d commit f0473d5

6 files changed

Lines changed: 103 additions & 13 deletions

File tree

Doc/lib/libsys.tex

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,13 @@ \section{\module{sys} ---
180180
\versionadded{2.0}
181181
\end{funcdesc}
182182

183+
\begin{funcdesc}{getdlopenflags}{}
184+
Return the current value of the flags that are used for \code{dlopen}
185+
calls. The flag constants are defined in the \refmodule{dl} and
186+
\module{DLFCN} modules.
187+
\versionadded{2.2}
188+
\end{funcdesc}
189+
183190
\begin{funcdesc}{getrefcount}{object}
184191
Return the reference count of the \var{object}. The count returned is
185192
generally one higher than you might expect, because it includes the
@@ -333,6 +340,20 @@ \section{\module{sys} ---
333340
\versionadded{2.0}
334341
\end{funcdesc}
335342

343+
\begin{funcdesc}{sertdlopenflags}{n}
344+
Set the flags that will be used for \code{dlopen()} calls, i.e. when
345+
the interpreter loads extension modules. Among other things, this
346+
will enable a lazy resolving of symbols when imporing a module, if
347+
called as \code{sys.setdlopenflags(0)}. To share symols across
348+
extension modules, call as
349+
\code{sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)}. The symbolic
350+
names for the flag modules can be either found in the \refmodule{dl}
351+
module, or in the \module{DLFCN} module. If \module{DLFCN} is not
352+
available, it can be generated from \code{/usr/include/dlfcn.h} using
353+
the \code{h2py} script.
354+
\versionadded{2.2}
355+
\end{funcdesc}
356+
336357
\begin{funcdesc}{setprofile}{profilefunc}
337358
Set the system's profile function, which allows you to implement a
338359
Python source code profiler in Python. See the chapter on the

Include/pystate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ typedef struct _is {
2323
PyObject *builtins;
2424

2525
int checkinterval;
26+
#ifdef HAVE_DLOPEN
27+
int dlopenflags;
28+
#endif
2629

2730
} PyInterpreterState;
2831

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ Core
149149

150150
Library
151151

152+
- The flags used in dlopen calls can now be configured using
153+
sys.setdlopenflags and queried using sys.getdlopenflags.
154+
152155
- Fredrik Lundh's xmlrpclib is now a standard library module. This
153156
provides full client-side XML-RPC support. In addition,
154157
Demo/xmlrpc/ contains two server frameworks (one SocketServer-based,

Python/dynload_shlib.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@
2222
#define LEAD_UNDERSCORE ""
2323
#endif
2424

25-
#ifndef RTLD_LAZY
26-
#define RTLD_LAZY 1
27-
#endif
28-
2925

3026
const struct filedescr _PyImport_DynLoadFiletab[] = {
3127
#ifdef __CYGWIN__
@@ -53,6 +49,7 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
5349
void *handle;
5450
char funcname[258];
5551
char pathbuf[260];
52+
int dlopenflags=0;
5653

5754
if (strchr(pathname, '/') == NULL) {
5855
/* Prefix bare filename with "./" */
@@ -80,16 +77,13 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
8077
}
8178
}
8279

83-
#ifdef RTLD_NOW
84-
/* RTLD_NOW: resolve externals now
85-
(i.e. core dump now if some are missing) */
86-
handle = dlopen(pathname, RTLD_NOW);
87-
#else
80+
dlopenflags = PyThreadState_Get()->interp->dlopenflags;
81+
8882
if (Py_VerboseFlag)
89-
printf("dlopen(\"%s\", %d);\n", pathname,
90-
RTLD_LAZY);
91-
handle = dlopen(pathname, RTLD_LAZY);
92-
#endif /* RTLD_NOW */
83+
printf("dlopen(\"%s\", %x);\n", pathname, dlopenflags);
84+
85+
handle = dlopen(pathname, dlopenflags);
86+
9387
if (handle == NULL) {
9488
PyErr_SetString(PyExc_ImportError, dlerror());
9589
return NULL;

Python/pystate.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33

44
#include "Python.h"
55

6+
#ifdef HAVE_DLOPEN
7+
#ifdef HAVE_DLFCN_H
8+
#include <dlfcn.h>
9+
#endif
10+
#ifndef RTLD_LAZY
11+
#define RTLD_LAZY 1
12+
#endif
13+
#endif
14+
15+
616
#define ZAP(x) { \
717
PyObject *tmp = (PyObject *)(x); \
818
(x) = NULL; \
@@ -39,6 +49,13 @@ PyInterpreterState_New(void)
3949
interp->builtins = NULL;
4050
interp->checkinterval = 10;
4151
interp->tstate_head = NULL;
52+
#ifdef HAVE_DLOPEN
53+
#ifdef RTLD_NOW
54+
interp->dlopenflags = RTLD_NOW;
55+
#else
56+
interp->dlopenflags = RTLD_LAZY;
57+
#endif
58+
#endif
4259

4360
HEAD_LOCK();
4461
interp->next = interp_head;

Python/sysmodule.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,48 @@ Return the current value of the recursion limit, the maximum depth\n\
394394
of the Python interpreter stack. This limit prevents infinite\n\
395395
recursion from causing an overflow of the C stack and crashing Python.";
396396

397+
#ifdef HAVE_DLOPEN
398+
static PyObject *
399+
sys_setdlopenflags(PyObject *self, PyObject *args)
400+
{
401+
int new_val;
402+
PyThreadState *tstate = PyThreadState_Get();
403+
if (!PyArg_ParseTuple(args, "i:setdlopenflags", &new_val))
404+
return NULL;
405+
if (!tstate)
406+
return NULL;
407+
tstate->interp->dlopenflags = new_val;
408+
Py_INCREF(Py_None);
409+
return Py_None;
410+
}
411+
412+
static char setdlopenflags_doc[] =
413+
"setdlopenflags(n) -> None\n\
414+
\n\
415+
Set the flags that will be used for dlopen() calls. Among other\n\
416+
things, this will enable a lazy resolving of symbols when imporing\n\
417+
a module, if called as sys.setdlopenflags(0)\n\
418+
To share symols across extension modules, call as\n\
419+
sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)";
420+
421+
static PyObject *
422+
sys_getdlopenflags(PyObject *self, PyObject *args)
423+
{
424+
PyThreadState *tstate = PyThreadState_Get();
425+
if (!PyArg_ParseTuple(args, ":getdlopenflags"))
426+
return NULL;
427+
if (!tstate)
428+
return NULL;
429+
return PyInt_FromLong(tstate->interp->dlopenflags);
430+
}
431+
432+
static char getdlopenflags_doc[] =
433+
"getdlopenflags() -> int\n\
434+
\n\
435+
Return the current value of the flags that are used for dlopen()\n\
436+
calls. The flag constants are defined in the dl module.";
437+
#endif
438+
397439
#ifdef USE_MALLOPT
398440
/* Link with -lmalloc (or -lmpc) on an SGI */
399441
#include <malloc.h>
@@ -501,6 +543,10 @@ static PyMethodDef sys_methods[] = {
501543
{"exit", sys_exit, 0, exit_doc},
502544
{"getdefaultencoding", sys_getdefaultencoding, 1,
503545
getdefaultencoding_doc},
546+
#ifdef HAVE_DLOPEN
547+
{"getdlopenflags", sys_getdlopenflags, 1,
548+
getdlopenflags_doc},
549+
#endif
504550
#ifdef COUNT_ALLOCS
505551
{"getcounts", sys_getcounts, 1},
506552
#endif
@@ -522,6 +568,10 @@ static PyMethodDef sys_methods[] = {
522568
setdefaultencoding_doc},
523569
{"setcheckinterval", sys_setcheckinterval, 1,
524570
setcheckinterval_doc},
571+
#ifdef HAVE_DLOPEN
572+
{"setdlopenflags", sys_setdlopenflags, 1,
573+
setdlopenflags_doc},
574+
#endif
525575
{"setprofile", sys_setprofile, 0, setprofile_doc},
526576
{"setrecursionlimit", sys_setrecursionlimit, 1,
527577
setrecursionlimit_doc},
@@ -659,9 +709,11 @@ displayhook() -- print an object to the screen, and save it in __builtin__._\n\
659709
excepthook() -- print an exception and its traceback to sys.stderr\n\
660710
exc_info() -- return thread-safe information about the current exception\n\
661711
exit() -- exit the interpreter by raising SystemExit\n\
712+
getdlopenflags() -- returns flags to be used for dlopen() calls\n\
662713
getrefcount() -- return the reference count for an object (plus one :-)\n\
663714
getrecursionlimit() -- return the max recursion depth for the interpreter\n\
664715
setcheckinterval() -- control how often the interpreter checks for events\n\
716+
setdlopenflags() -- set the flags to be used for dlopen() calls\n\
665717
setprofile() -- set the global profiling function\n\
666718
setrecursionlimit() -- set the max recursion depth for the interpreter\n\
667719
settrace() -- set the global debug tracing function\n\

0 commit comments

Comments
 (0)