Patch #412229: Add functions sys.getdlopenflags and sys.setdlopenflags.

Add dlopenflags to PyInterpreterState, and use it in dlopen calls.
This commit is contained in:
Martin v. Löwis 2001-07-18 16:17:16 +00:00
parent 984158d25b
commit f0473d511b
6 changed files with 103 additions and 13 deletions

View File

@ -180,6 +180,13 @@ way to exit a program when an error occurs.
\versionadded{2.0} \versionadded{2.0}
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{getdlopenflags}{}
Return the current value of the flags that are used for \code{dlopen}
calls. The flag constants are defined in the \refmodule{dl} and
\module{DLFCN} modules.
\versionadded{2.2}
\end{funcdesc}
\begin{funcdesc}{getrefcount}{object} \begin{funcdesc}{getrefcount}{object}
Return the reference count of the \var{object}. The count returned is Return the reference count of the \var{object}. The count returned is
generally one higher than you might expect, because it includes the generally one higher than you might expect, because it includes the
@ -333,6 +340,20 @@ maximizing responsiveness as well as overhead.
\versionadded{2.0} \versionadded{2.0}
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{sertdlopenflags}{n}
Set the flags that will be used for \code{dlopen()} calls, i.e. when
the interpreter loads extension modules. Among other things, this
will enable a lazy resolving of symbols when imporing a module, if
called as \code{sys.setdlopenflags(0)}. To share symols across
extension modules, call as
\code{sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)}. The symbolic
names for the flag modules can be either found in the \refmodule{dl}
module, or in the \module{DLFCN} module. If \module{DLFCN} is not
available, it can be generated from \code{/usr/include/dlfcn.h} using
the \code{h2py} script.
\versionadded{2.2}
\end{funcdesc}
\begin{funcdesc}{setprofile}{profilefunc} \begin{funcdesc}{setprofile}{profilefunc}
Set the system's profile function, which allows you to implement a Set the system's profile function, which allows you to implement a
Python source code profiler in Python. See the chapter on the Python source code profiler in Python. See the chapter on the

View File

@ -23,6 +23,9 @@ typedef struct _is {
PyObject *builtins; PyObject *builtins;
int checkinterval; int checkinterval;
#ifdef HAVE_DLOPEN
int dlopenflags;
#endif
} PyInterpreterState; } PyInterpreterState;

View File

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

View File

@ -22,10 +22,6 @@
#define LEAD_UNDERSCORE "" #define LEAD_UNDERSCORE ""
#endif #endif
#ifndef RTLD_LAZY
#define RTLD_LAZY 1
#endif
const struct filedescr _PyImport_DynLoadFiletab[] = { const struct filedescr _PyImport_DynLoadFiletab[] = {
#ifdef __CYGWIN__ #ifdef __CYGWIN__
@ -53,6 +49,7 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
void *handle; void *handle;
char funcname[258]; char funcname[258];
char pathbuf[260]; char pathbuf[260];
int dlopenflags=0;
if (strchr(pathname, '/') == NULL) { if (strchr(pathname, '/') == NULL) {
/* Prefix bare filename with "./" */ /* Prefix bare filename with "./" */
@ -80,16 +77,13 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
} }
} }
#ifdef RTLD_NOW dlopenflags = PyThreadState_Get()->interp->dlopenflags;
/* RTLD_NOW: resolve externals now
(i.e. core dump now if some are missing) */
handle = dlopen(pathname, RTLD_NOW);
#else
if (Py_VerboseFlag) if (Py_VerboseFlag)
printf("dlopen(\"%s\", %d);\n", pathname, printf("dlopen(\"%s\", %x);\n", pathname, dlopenflags);
RTLD_LAZY);
handle = dlopen(pathname, RTLD_LAZY); handle = dlopen(pathname, dlopenflags);
#endif /* RTLD_NOW */
if (handle == NULL) { if (handle == NULL) {
PyErr_SetString(PyExc_ImportError, dlerror()); PyErr_SetString(PyExc_ImportError, dlerror());
return NULL; return NULL;

View File

@ -3,6 +3,16 @@
#include "Python.h" #include "Python.h"
#ifdef HAVE_DLOPEN
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#ifndef RTLD_LAZY
#define RTLD_LAZY 1
#endif
#endif
#define ZAP(x) { \ #define ZAP(x) { \
PyObject *tmp = (PyObject *)(x); \ PyObject *tmp = (PyObject *)(x); \
(x) = NULL; \ (x) = NULL; \
@ -39,6 +49,13 @@ PyInterpreterState_New(void)
interp->builtins = NULL; interp->builtins = NULL;
interp->checkinterval = 10; interp->checkinterval = 10;
interp->tstate_head = NULL; interp->tstate_head = NULL;
#ifdef HAVE_DLOPEN
#ifdef RTLD_NOW
interp->dlopenflags = RTLD_NOW;
#else
interp->dlopenflags = RTLD_LAZY;
#endif
#endif
HEAD_LOCK(); HEAD_LOCK();
interp->next = interp_head; interp->next = interp_head;

View File

@ -394,6 +394,48 @@ Return the current value of the recursion limit, the maximum depth\n\
of the Python interpreter stack. This limit prevents infinite\n\ of the Python interpreter stack. This limit prevents infinite\n\
recursion from causing an overflow of the C stack and crashing Python."; recursion from causing an overflow of the C stack and crashing Python.";
#ifdef HAVE_DLOPEN
static PyObject *
sys_setdlopenflags(PyObject *self, PyObject *args)
{
int new_val;
PyThreadState *tstate = PyThreadState_Get();
if (!PyArg_ParseTuple(args, "i:setdlopenflags", &new_val))
return NULL;
if (!tstate)
return NULL;
tstate->interp->dlopenflags = new_val;
Py_INCREF(Py_None);
return Py_None;
}
static char setdlopenflags_doc[] =
"setdlopenflags(n) -> None\n\
\n\
Set the flags that will be used for dlopen() calls. Among other\n\
things, this will enable a lazy resolving of symbols when imporing\n\
a module, if called as sys.setdlopenflags(0)\n\
To share symols across extension modules, call as\n\
sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)";
static PyObject *
sys_getdlopenflags(PyObject *self, PyObject *args)
{
PyThreadState *tstate = PyThreadState_Get();
if (!PyArg_ParseTuple(args, ":getdlopenflags"))
return NULL;
if (!tstate)
return NULL;
return PyInt_FromLong(tstate->interp->dlopenflags);
}
static char getdlopenflags_doc[] =
"getdlopenflags() -> int\n\
\n\
Return the current value of the flags that are used for dlopen()\n\
calls. The flag constants are defined in the dl module.";
#endif
#ifdef USE_MALLOPT #ifdef USE_MALLOPT
/* Link with -lmalloc (or -lmpc) on an SGI */ /* Link with -lmalloc (or -lmpc) on an SGI */
#include <malloc.h> #include <malloc.h>
@ -501,6 +543,10 @@ static PyMethodDef sys_methods[] = {
{"exit", sys_exit, 0, exit_doc}, {"exit", sys_exit, 0, exit_doc},
{"getdefaultencoding", sys_getdefaultencoding, 1, {"getdefaultencoding", sys_getdefaultencoding, 1,
getdefaultencoding_doc}, getdefaultencoding_doc},
#ifdef HAVE_DLOPEN
{"getdlopenflags", sys_getdlopenflags, 1,
getdlopenflags_doc},
#endif
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
{"getcounts", sys_getcounts, 1}, {"getcounts", sys_getcounts, 1},
#endif #endif
@ -522,6 +568,10 @@ static PyMethodDef sys_methods[] = {
setdefaultencoding_doc}, setdefaultencoding_doc},
{"setcheckinterval", sys_setcheckinterval, 1, {"setcheckinterval", sys_setcheckinterval, 1,
setcheckinterval_doc}, setcheckinterval_doc},
#ifdef HAVE_DLOPEN
{"setdlopenflags", sys_setdlopenflags, 1,
setdlopenflags_doc},
#endif
{"setprofile", sys_setprofile, 0, setprofile_doc}, {"setprofile", sys_setprofile, 0, setprofile_doc},
{"setrecursionlimit", sys_setrecursionlimit, 1, {"setrecursionlimit", sys_setrecursionlimit, 1,
setrecursionlimit_doc}, setrecursionlimit_doc},
@ -659,9 +709,11 @@ displayhook() -- print an object to the screen, and save it in __builtin__._\n\
excepthook() -- print an exception and its traceback to sys.stderr\n\ excepthook() -- print an exception and its traceback to sys.stderr\n\
exc_info() -- return thread-safe information about the current exception\n\ exc_info() -- return thread-safe information about the current exception\n\
exit() -- exit the interpreter by raising SystemExit\n\ exit() -- exit the interpreter by raising SystemExit\n\
getdlopenflags() -- returns flags to be used for dlopen() calls\n\
getrefcount() -- return the reference count for an object (plus one :-)\n\ getrefcount() -- return the reference count for an object (plus one :-)\n\
getrecursionlimit() -- return the max recursion depth for the interpreter\n\ getrecursionlimit() -- return the max recursion depth for the interpreter\n\
setcheckinterval() -- control how often the interpreter checks for events\n\ setcheckinterval() -- control how often the interpreter checks for events\n\
setdlopenflags() -- set the flags to be used for dlopen() calls\n\
setprofile() -- set the global profiling function\n\ setprofile() -- set the global profiling function\n\
setrecursionlimit() -- set the max recursion depth for the interpreter\n\ setrecursionlimit() -- set the max recursion depth for the interpreter\n\
settrace() -- set the global debug tracing function\n\ settrace() -- set the global debug tracing function\n\