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:
parent
bea8ae7948
commit
1df1536fb9
|
@ -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?
|
||||||
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)
|
||||||
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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue