Index: Python/ceval.c =================================================================== --- Python/ceval.c (révision 84741) +++ Python/ceval.c (copie de travail) @@ -313,6 +313,15 @@ } void +_PyEval_FiniThreads(void) +{ + if (!gil_created()) + return; + destroy_gil(); + assert(!gil_created()); +} + +void PyEval_AcquireLock(void) { PyThreadState *tstate = PyThreadState_GET(); @@ -368,10 +377,6 @@ if (!gil_created()) 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(); pending_lock = PyThread_allocate_lock(); take_gil(tstate); Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (révision 84741) +++ Python/pythonrun.c (copie de travail) @@ -217,8 +217,13 @@ Py_FatalError("Py_Initialize: can't make first thread"); (void) PyThreadState_Swap(tstate); - /* auto-thread-state API, if available */ #ifdef WITH_THREAD + /* If the GIL was already initialized (by a previous interpreter session), + re-initialize it. + XXX this will leak system resources accross multiple calls to + Py_Initialize() */ +/* if (PyEval_ThreadsInitialized()) + PyEval_ReInitThreads();*/ _PyGILState_Init(interp, tstate); #endif /* WITH_THREAD */ @@ -514,6 +519,10 @@ PyGrammar_RemoveAccelerators(&_PyParser_Grammar); +#ifdef WITH_THREAD + _PyEval_FiniThreads(); +#endif + #ifdef Py_TRACE_REFS /* Display addresses (& refcnts) of all objects still alive. * An address can be used to find the repr of the object, printed Index: Python/ceval_gil.h =================================================================== --- Python/ceval_gil.h (révision 84741) +++ Python/ceval_gil.h (copie de travail) @@ -95,6 +95,9 @@ #define MUTEX_INIT(mut) \ if (pthread_mutex_init(&mut, NULL)) { \ 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) \ if (pthread_mutex_lock(&mut)) { \ Py_FatalError("pthread_mutex_lock(" #mut ") failed"); }; @@ -106,6 +109,9 @@ #define COND_INIT(cond) \ if (pthread_cond_init(&cond, NULL)) { \ 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) \ if (pthread_cond_signal(&cond)) { \ Py_FatalError("pthread_cond_signal(" #cond ") failed"); }; @@ -305,6 +311,20 @@ _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) { _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked); Index: Include/ceval.h =================================================================== --- Include/ceval.h (révision 84741) +++ Include/ceval.h (copie de travail) @@ -160,6 +160,7 @@ PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); PyAPI_FUNC(void) PyEval_InitThreads(void); +PyAPI_FUNC(void) _PyEval_FiniThreads(void); PyAPI_FUNC(void) PyEval_AcquireLock(void); PyAPI_FUNC(void) PyEval_ReleaseLock(void); PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);