Commit 1df1536f authored by Antoine Pitrou's avatar Antoine Pitrou

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.
parent bea8ae79
...@@ -160,6 +160,7 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); ...@@ -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);
......
...@@ -10,6 +10,10 @@ What's New in Python 3.2 Alpha 3? ...@@ -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.
......
...@@ -312,6 +312,15 @@ PyEval_InitThreads(void) ...@@ -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) ...@@ -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);
......
...@@ -95,6 +95,9 @@ do { \ ...@@ -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 { \ ...@@ -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) ...@@ -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();
} }
......
...@@ -514,6 +514,10 @@ Py_Finalize(void) ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment