Skip to content

Commit 1df1536

Browse files
committed
Issue python#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.
1 parent bea8ae7 commit 1df1536

5 files changed

Lines changed: 39 additions & 4 deletions

File tree

Include/ceval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *);
160160

161161
PyAPI_FUNC(int) PyEval_ThreadsInitialized(void);
162162
PyAPI_FUNC(void) PyEval_InitThreads(void);
163+
PyAPI_FUNC(void) _PyEval_FiniThreads(void);
163164
PyAPI_FUNC(void) PyEval_AcquireLock(void);
164165
PyAPI_FUNC(void) PyEval_ReleaseLock(void);
165166
PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ What's New in Python 3.2 Alpha 3?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly
14+
re-created on a subsequent call to Py_Initialize(). The problem (a crash)
15+
wouldn't appear in 3.1 or 2.7 where the GIL's structure is more trivial.
16+
1317
- Issue #9210: Configure option --with-wctype-functions was removed. Using the
1418
functions from the libc caused the methods .upper() and lower() to become
1519
locale aware and created subtly wrong results.

Python/ceval.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,15 @@ PyEval_InitThreads(void)
312312
pending_lock = PyThread_allocate_lock();
313313
}
314314

315+
void
316+
_PyEval_FiniThreads(void)
317+
{
318+
if (!gil_created())
319+
return;
320+
destroy_gil();
321+
assert(!gil_created());
322+
}
323+
315324
void
316325
PyEval_AcquireLock(void)
317326
{
@@ -368,10 +377,6 @@ PyEval_ReInitThreads(void)
368377

369378
if (!gil_created())
370379
return;
371-
/*XXX Can't use PyThread_free_lock here because it does too
372-
much error-checking. Doing this cleanly would require
373-
adding a new function to each thread_*.h. Instead, just
374-
create a new lock and waste a little bit of memory */
375380
recreate_gil();
376381
pending_lock = PyThread_allocate_lock();
377382
take_gil(tstate);

Python/ceval_gil.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ do { \
9595
#define MUTEX_INIT(mut) \
9696
if (pthread_mutex_init(&mut, NULL)) { \
9797
Py_FatalError("pthread_mutex_init(" #mut ") failed"); };
98+
#define MUTEX_FINI(mut) \
99+
if (pthread_mutex_destroy(&mut)) { \
100+
Py_FatalError("pthread_mutex_destroy(" #mut ") failed"); };
98101
#define MUTEX_LOCK(mut) \
99102
if (pthread_mutex_lock(&mut)) { \
100103
Py_FatalError("pthread_mutex_lock(" #mut ") failed"); };
@@ -106,6 +109,9 @@ do { \
106109
#define COND_INIT(cond) \
107110
if (pthread_cond_init(&cond, NULL)) { \
108111
Py_FatalError("pthread_cond_init(" #cond ") failed"); };
112+
#define COND_FINI(cond) \
113+
if (pthread_cond_destroy(&cond)) { \
114+
Py_FatalError("pthread_cond_destroy(" #cond ") failed"); };
109115
#define COND_SIGNAL(cond) \
110116
if (pthread_cond_signal(&cond)) { \
111117
Py_FatalError("pthread_cond_signal(" #cond ") failed"); };
@@ -305,9 +311,24 @@ static void create_gil(void)
305311
_Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release);
306312
}
307313

314+
static void destroy_gil(void)
315+
{
316+
MUTEX_FINI(gil_mutex);
317+
#ifdef FORCE_SWITCHING
318+
MUTEX_FINI(switch_mutex);
319+
#endif
320+
COND_FINI(gil_cond);
321+
#ifdef FORCE_SWITCHING
322+
COND_FINI(switch_cond);
323+
#endif
324+
_Py_atomic_store_explicit(&gil_locked, -1, _Py_memory_order_release);
325+
_Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked);
326+
}
327+
308328
static void recreate_gil(void)
309329
{
310330
_Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked);
331+
/* XXX should we destroy the old OS resources here? */
311332
create_gil();
312333
}
313334

Python/pythonrun.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,10 @@ Py_Finalize(void)
514514

515515
PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
516516

517+
#ifdef WITH_THREAD
518+
_PyEval_FiniThreads();
519+
#endif
520+
517521
#ifdef Py_TRACE_REFS
518522
/* Display addresses (& refcnts) of all objects still alive.
519523
* An address can be used to find the repr of the object, printed

0 commit comments

Comments
 (0)