Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly

re-created on a subsequent call to Py_Initialize().  The problem (a crash)
wouldn't appear in 3.1 or 2.7 where the GIL's structure is more trivial.
This commit is contained in:
Antoine Pitrou 2010-09-13 14:16:46 +00:00
parent bea8ae7948
commit 1df1536fb9
5 changed files with 39 additions and 4 deletions

View File

@ -160,6 +160,7 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *);
PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); PyAPI_FUNC(int) PyEval_ThreadsInitialized(void);
PyAPI_FUNC(void) PyEval_InitThreads(void); PyAPI_FUNC(void) PyEval_InitThreads(void);
PyAPI_FUNC(void) _PyEval_FiniThreads(void);
PyAPI_FUNC(void) PyEval_AcquireLock(void); PyAPI_FUNC(void) PyEval_AcquireLock(void);
PyAPI_FUNC(void) PyEval_ReleaseLock(void); PyAPI_FUNC(void) PyEval_ReleaseLock(void);
PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate); PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);

View File

@ -10,6 +10,10 @@ What's New in Python 3.2 Alpha 3?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
re-created on a subsequent call to Py_Initialize(). The problem (a crash)
wouldn't appear in 3.1 or 2.7 where the GIL's structure is more trivial.
- Issue #9210: Configure option --with-wctype-functions was removed. Using the - Issue #9210: Configure option --with-wctype-functions was removed. Using the
functions from the libc caused the methods .upper() and lower() to become functions from the libc caused the methods .upper() and lower() to become
locale aware and created subtly wrong results. locale aware and created subtly wrong results.

View File

@ -312,6 +312,15 @@ PyEval_InitThreads(void)
pending_lock = PyThread_allocate_lock(); pending_lock = PyThread_allocate_lock();
} }
void
_PyEval_FiniThreads(void)
{
if (!gil_created())
return;
destroy_gil();
assert(!gil_created());
}
void void
PyEval_AcquireLock(void) PyEval_AcquireLock(void)
{ {
@ -368,10 +377,6 @@ PyEval_ReInitThreads(void)
if (!gil_created()) if (!gil_created())
return; return;
/*XXX Can't use PyThread_free_lock here because it does too
much error-checking. Doing this cleanly would require
adding a new function to each thread_*.h. Instead, just
create a new lock and waste a little bit of memory */
recreate_gil(); recreate_gil();
pending_lock = PyThread_allocate_lock(); pending_lock = PyThread_allocate_lock();
take_gil(tstate); take_gil(tstate);

View File

@ -95,6 +95,9 @@ do { \
#define MUTEX_INIT(mut) \ #define MUTEX_INIT(mut) \
if (pthread_mutex_init(&mut, NULL)) { \ if (pthread_mutex_init(&mut, NULL)) { \
Py_FatalError("pthread_mutex_init(" #mut ") failed"); }; Py_FatalError("pthread_mutex_init(" #mut ") failed"); };
#define MUTEX_FINI(mut) \
if (pthread_mutex_destroy(&mut)) { \
Py_FatalError("pthread_mutex_destroy(" #mut ") failed"); };
#define MUTEX_LOCK(mut) \ #define MUTEX_LOCK(mut) \
if (pthread_mutex_lock(&mut)) { \ if (pthread_mutex_lock(&mut)) { \
Py_FatalError("pthread_mutex_lock(" #mut ") failed"); }; Py_FatalError("pthread_mutex_lock(" #mut ") failed"); };
@ -106,6 +109,9 @@ do { \
#define COND_INIT(cond) \ #define COND_INIT(cond) \
if (pthread_cond_init(&cond, NULL)) { \ if (pthread_cond_init(&cond, NULL)) { \
Py_FatalError("pthread_cond_init(" #cond ") failed"); }; Py_FatalError("pthread_cond_init(" #cond ") failed"); };
#define COND_FINI(cond) \
if (pthread_cond_destroy(&cond)) { \
Py_FatalError("pthread_cond_destroy(" #cond ") failed"); };
#define COND_SIGNAL(cond) \ #define COND_SIGNAL(cond) \
if (pthread_cond_signal(&cond)) { \ if (pthread_cond_signal(&cond)) { \
Py_FatalError("pthread_cond_signal(" #cond ") failed"); }; Py_FatalError("pthread_cond_signal(" #cond ") failed"); };
@ -305,9 +311,24 @@ static void create_gil(void)
_Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release); _Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release);
} }
static void destroy_gil(void)
{
MUTEX_FINI(gil_mutex);
#ifdef FORCE_SWITCHING
MUTEX_FINI(switch_mutex);
#endif
COND_FINI(gil_cond);
#ifdef FORCE_SWITCHING
COND_FINI(switch_cond);
#endif
_Py_atomic_store_explicit(&gil_locked, -1, _Py_memory_order_release);
_Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked);
}
static void recreate_gil(void) static void recreate_gil(void)
{ {
_Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked); _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked);
/* XXX should we destroy the old OS resources here? */
create_gil(); create_gil();
} }

View File

@ -514,6 +514,10 @@ Py_Finalize(void)
PyGrammar_RemoveAccelerators(&_PyParser_Grammar); PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
#ifdef WITH_THREAD
_PyEval_FiniThreads();
#endif
#ifdef Py_TRACE_REFS #ifdef Py_TRACE_REFS
/* Display addresses (& refcnts) of all objects still alive. /* Display addresses (& refcnts) of all objects still alive.
* An address can be used to find the repr of the object, printed * An address can be used to find the repr of the object, printed