[Python-checkins] r81174 - in python/branches/py3k-jit: Include/ceval.h Makefile.pre.in Python/ceval.c Python/ceval_gil.h Python/pythonrun.c Unittests/ThreadTest.cc
jeffrey.yasskin
python-checkins at python.org
Fri May 14 20:51:40 CEST 2010
Author: jeffrey.yasskin
Date: Fri May 14 20:51:40 2010
New Revision: 81174
Log:
Fix a problem where initializing threads and then finalizing and
re-initializing the interpreter would cause any use of the gil to crash.
Added:
python/branches/py3k-jit/Unittests/ThreadTest.cc
Modified:
python/branches/py3k-jit/Include/ceval.h
python/branches/py3k-jit/Makefile.pre.in
python/branches/py3k-jit/Python/ceval.c
python/branches/py3k-jit/Python/ceval_gil.h
python/branches/py3k-jit/Python/pythonrun.c
Modified: python/branches/py3k-jit/Include/ceval.h
==============================================================================
--- python/branches/py3k-jit/Include/ceval.h (original)
+++ python/branches/py3k-jit/Include/ceval.h Fri May 14 20:51:40 2010
@@ -165,6 +165,7 @@
PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);
PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate);
PyAPI_FUNC(void) PyEval_ReInitThreads(void);
+PyAPI_FUNC(void) PyEval_UnInitThreads(void);
PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds);
PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void);
Modified: python/branches/py3k-jit/Makefile.pre.in
==============================================================================
--- python/branches/py3k-jit/Makefile.pre.in (original)
+++ python/branches/py3k-jit/Makefile.pre.in Fri May 14 20:51:40 2010
@@ -751,6 +751,7 @@
$(srcdir)/Unittests/GetArgsTest.cc \
$(srcdir)/Unittests/ListTest.cc \
$(srcdir)/Unittests/ObjectTest.cc \
+ $(srcdir)/Unittests/ThreadTest.cc \
$(srcdir)/Unittests/UnicodeTest.cc \
$(srcdir)/Unittests/pytest_main.cc \
$(@LLVM_UNITTEST_SRCS@) \
Modified: python/branches/py3k-jit/Python/ceval.c
==============================================================================
--- python/branches/py3k-jit/Python/ceval.c (original)
+++ python/branches/py3k-jit/Python/ceval.c Fri May 14 20:51:40 2010
@@ -389,6 +389,16 @@
Py_DECREF(threading);
}
+/* This function is called from Py_Finalize to destroy the gil. No
+ other threads may be running when it is called. */
+void
+PyEval_UnInitThreads(void)
+{
+ if (!gil_created())
+ return;
+ destroy_gil();
+}
+
#else
static _Py_atomic_int eval_breaker = {0};
static _Py_atomic_int gil_drop_request = {0};
Modified: python/branches/py3k-jit/Python/ceval_gil.h
==============================================================================
--- python/branches/py3k-jit/Python/ceval_gil.h (original)
+++ python/branches/py3k-jit/Python/ceval_gil.h Fri May 14 20:51:40 2010
@@ -95,6 +95,9 @@
#define MUTEX_INIT(mut) \
if (pthread_mutex_init(&mut, NULL)) { \
Py_FatalError("pthread_mutex_init(" #mut ") failed"); };
+#define MUTEX_DESTROY(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_DESTROY(cond) \
+ if (pthread_cond_destroy(&cond)) { \
+ Py_FatalError("pthread_cond_destroy(" #cond ") failed"); };
#define COND_RESET(cond)
#define COND_SIGNAL(cond) \
if (pthread_cond_signal(&cond)) { \
@@ -145,6 +151,9 @@
#define MUTEX_INIT(mut) \
if (!(mut = CreateMutex(NULL, FALSE, NULL))) { \
Py_FatalError("CreateMutex(" #mut ") failed"); };
+#define MUTEX_DESTROY(mut) \
+ if (!CloseHandle(mut)) { \
+ Py_FatalError("CloseHandle(" #mut ") failed to destroy mutex"); };
#define MUTEX_LOCK(mut) \
if (WaitForSingleObject(mut, INFINITE) != WAIT_OBJECT_0) { \
Py_FatalError("WaitForSingleObject(" #mut ") failed"); };
@@ -172,6 +181,9 @@
/* auto-reset, non-signalled */ \
if (!(cond = CreateEvent(NULL, FALSE, FALSE, NULL))) { \
Py_FatalError("CreateMutex(" #cond ") failed"); };
+#define COND_DESTROY(cond) \
+ if (!CloseHandle(cond)) { \
+ Py_FatalError("CloseHandle(" #cond ") failed to destroy event"); };
#define COND_RESET(cond) \
if (!ResetEvent(cond)) { \
Py_FatalError("ResetEvent(" #cond ") failed"); };
@@ -256,6 +268,21 @@
create_gil();
}
+/* Requires that no other threads are running anymore. */
+static void destroy_gil(void)
+{
+ MUTEX_DESTROY(gil_mutex);
+#ifdef FORCE_SWITCHING
+ MUTEX_DESTROY(switch_mutex);
+#endif
+ COND_DESTROY(gil_cond);
+#ifdef FORCE_SWITCHING
+ COND_DESTROY(switch_cond);
+#endif
+ _Py_atomic_store_relaxed(&gil_locked, -1);
+ _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked);
+}
+
static void drop_gil(PyThreadState *tstate)
{
/* NOTE: tstate is allowed to be NULL. */
Modified: python/branches/py3k-jit/Python/pythonrun.c
==============================================================================
--- python/branches/py3k-jit/Python/pythonrun.c (original)
+++ python/branches/py3k-jit/Python/pythonrun.c Fri May 14 20:51:40 2010
@@ -478,6 +478,7 @@
/* Delete current thread */
PyThreadState_Swap(NULL);
PyInterpreterState_Delete(interp);
+ PyEval_UnInitThreads();
/* Sundry finalizers */
PyMethod_Fini();
Added: python/branches/py3k-jit/Unittests/ThreadTest.cc
==============================================================================
--- (empty file)
+++ python/branches/py3k-jit/Unittests/ThreadTest.cc Fri May 14 20:51:40 2010
@@ -0,0 +1,28 @@
+#include "Python.h"
+
+#include "gtest/gtest.h"
+#include "pytest.h"
+
+namespace {
+
+class ThreadTest : public ::testing::Test {
+ PythonSetupTeardown setup_teardown_;
+};
+
+TEST_F(ThreadTest, InitThreadsAcrossFinalize)
+{
+ PyEval_InitThreads();
+
+ Py_Finalize();
+ // Make it more likely that we get a different address for the
+ // PyThreadState in the new interpreter.
+ void *p = malloc(sizeof(PyThreadState));
+ Py_Initialize();
+ free(p);
+
+ PyEval_InitThreads();
+ Py_BEGIN_ALLOW_THREADS; // Used to crash.
+ Py_END_ALLOW_THREADS;
+}
+
+} // anonymous namespace
More information about the Python-checkins
mailing list