Index: subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c =================================================================== --- subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c (revision 16776) +++ subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c (working copy) @@ -42,59 +42,37 @@ #include "swigutil_py.h" - /*** Manage the Global Interpreter Lock ***/ /* If both Python and APR have threads available, we can optimize ourselves * by releasing the global interpreter lock when we drop into our SVN calls. * - * In svn_types.i, svn_swig_py_release_py_lock is called before every - * function, then svn_swig_py_acquire_py_lock is called after every - * function. So, if these functions become no-ops, then Python will - * start to block... - * * The Subversion libraries can be assumed to be thread-safe *only* when * APR_HAS_THREAD is 1. The APR pool allocations aren't thread-safe unless * APR_HAS_THREAD is 1. */ - #if defined(WITH_THREAD) && APR_HAS_THREADS -#define ACQUIRE_PYTHON_LOCK +#if PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 3 +#define SVN_SWIG_PY_BEGIN_PYTHON_CALL \ + { PyGILState_STATE _save = PyGILState_UNLOCKED; \ + if (threads_terminated == 0) _save = PyGILState_Ensure(); +#define SVN_SWIG_PY_END_PYTHON_CALL \ + if (threads_terminated == 0) PyGILState_Release(_save); } +#else +#define SVN_SWIG_PY_BEGIN_PYTHON_CALL \ + { PyThreadState *_save = NULL; \ + if (threads_terminated == 0) { \ + _save = PyInterpreterState_ThreadHead(PyInterpreterState_Head()); \ + PyEval_AcquireThread(_save); \ + } +#define SVN_SWIG_PY_END_PYTHON_CALL \ + if (threads_terminated == 0) PyEval_ReleaseThread(_save); } #endif - -#ifdef ACQUIRE_PYTHON_LOCK -static apr_threadkey_t *_saved_thread_key = NULL; -static apr_pool_t *_saved_thread_pool = NULL; +#else +#define SVN_SWIG_PY_BEGIN_PYTHON_CALL +#define SVN_SWIG_PY_END_PYTHON_CALL #endif -void svn_swig_py_release_py_lock(void) -{ -#ifdef ACQUIRE_PYTHON_LOCK - PyThreadState *thread_state; - - if (_saved_thread_key == NULL) { - /* Obviously, creating a top-level pool for this is pretty stupid. */ - apr_pool_create(&_saved_thread_pool, NULL); - apr_threadkey_private_create(&_saved_thread_key, NULL, _saved_thread_pool); - } - - thread_state = PyEval_SaveThread(); - apr_threadkey_private_set(thread_state, _saved_thread_key); -#endif -} - -void svn_swig_py_acquire_py_lock(void) -{ -#ifdef ACQUIRE_PYTHON_LOCK - void *val; - PyThreadState *thread_state; - apr_threadkey_private_get(&val, _saved_thread_key); - thread_state = val; - PyEval_RestoreThread(thread_state); -#endif -} - - /*** Automatic Pool Management Functions ***/ @@ -109,16 +87,27 @@ static char setParentPool[] = "set_parent_pool"; static char emptyTuple[] = "()"; static char objectTuple[] = "(O)"; +static int threads_terminated = 0; +static void svn_swig_py__terminate(void) +{ + threads_terminated = 1; + apr_terminate(); +} apr_status_t svn_swig_py_initialize(void) { apr_status_t status; + Py_Initialize(); +#if defined(WITH_THREAD) && APR_HAS_THREADS + PyEval_InitThreads(); +#endif if ((status = apr_initialize()) != APR_SUCCESS) return status; - if (atexit(apr_terminate) != 0) + if (atexit(svn_swig_py__terminate) != 0) return APR_EGENERAL; + return APR_SUCCESS; } @@ -140,9 +129,9 @@ static apr_status_t svn_swig_py_pool_destroyed(void *ptr) { PyObject *pool = (PyObject *) ptr; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL PyObject_DelAttrString(pool, isValid); - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return APR_SUCCESS; } @@ -150,9 +139,9 @@ static apr_status_t svn_swig_py_pool_decref(void *ptr) { PyObject *pool = (PyObject *) ptr; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL Py_DECREF(pool); - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return APR_SUCCESS; } @@ -160,16 +149,17 @@ PyObject * svn_swig_py_register_cleanup(PyObject *py_pool, apr_pool_t *pool) { PyObject *result; + PyObject *retval = Py_None; - svn_swig_py_acquire_py_lock(); - /* Check that the pool object is valid */ + SVN_SWIG_PY_BEGIN_PYTHON_CALL result = PyObject_CallMethod(py_pool, assertValid, emptyTuple); if (result == NULL) { - return NULL; + retval = NULL; + goto finished; } + Py_DECREF(result); - svn_swig_py_release_py_lock(); /* Delete the "_isvalid" member when the pool is destroyed */ apr_pool_cleanup_register(pool, py_pool, svn_swig_py_pool_destroyed, @@ -177,7 +167,10 @@ /* Return None */ Py_INCREF(Py_None); - return Py_None; +finished: + SVN_SWIG_PY_END_PYTHON_CALL + + return retval; } /* Get the application pool */ @@ -910,7 +903,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* If there is no baton object, then it is an edit_baton, and we should not bother to pass an object. Note that we still shove a NULL onto @@ -940,7 +933,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -952,8 +945,8 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); - + SVN_SWIG_PY_BEGIN_PYTHON_CALL + /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"set_target_revision", (char *)"l", target_revision)) == NULL) @@ -967,7 +960,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -980,7 +973,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_root", @@ -996,7 +989,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1009,7 +1002,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry", @@ -1025,7 +1018,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1040,7 +1033,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory", @@ -1057,7 +1050,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1071,7 +1064,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory", @@ -1088,7 +1081,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1101,7 +1094,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_dir_prop", @@ -1119,7 +1112,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1140,7 +1133,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file", @@ -1158,7 +1151,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1172,7 +1165,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file", @@ -1189,7 +1182,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1200,7 +1193,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if (window == NULL) { @@ -1232,7 +1225,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1246,7 +1239,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"apply_textdelta", @@ -1278,7 +1271,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1291,7 +1284,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_file_prop", @@ -1309,7 +1302,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1321,7 +1314,7 @@ PyObject *result; svn_error_t *err; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"close_file", @@ -1348,7 +1341,7 @@ err = SVN_NO_ERROR; finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1453,7 +1446,7 @@ apr_size_t bytes; svn_error_t *err = SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallMethod(py_io, (char *)"read", (char *)"i", *len)) == NULL) { @@ -1478,7 +1471,7 @@ err = callback_bad_return_error("Not a string"); } Py_XDECREF(result); - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1492,14 +1485,14 @@ if (data != NULL) { - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallMethod(py_io, (char *)"write", (char *)"s#", data, *len)) == NULL) { err = callback_exception_error(); } Py_XDECREF(result); - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL } return err; @@ -1539,7 +1532,7 @@ if (function == NULL || function == Py_None) return; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"(siisiii)", path, action, kind, @@ -1561,7 +1554,7 @@ if (err) svn_error_clear(err); - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL } @@ -1576,7 +1569,7 @@ if (function == NULL || function == Py_None) return; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"sO&", path, make_ob_wc_status, status)) == NULL) { @@ -1594,7 +1587,7 @@ if (err) svn_error_clear(err); - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL } @@ -1607,7 +1600,7 @@ if (function == NULL || function == Py_None) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, NULL)) == NULL) { err = callback_exception_error(); @@ -1630,7 +1623,7 @@ } Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1645,7 +1638,7 @@ if (function == NULL || function == Py_None) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"O&O&", make_ob_lock, lock, @@ -1661,7 +1654,7 @@ Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1684,7 +1677,7 @@ if ((function == NULL) || (function == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if (commit_items) { @@ -1727,7 +1720,7 @@ } finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1748,7 +1741,7 @@ if (function == NULL || function == Py_None) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL py_pool = make_ob_pool(pool); if (py_pool == NULL) { @@ -1781,7 +1774,7 @@ Py_DECREF(py_root); Py_DECREF(py_pool); finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1798,7 +1791,7 @@ if (function == NULL || function == Py_None) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"slO&", path, revision, @@ -1812,7 +1805,7 @@ err = callback_bad_return_error("Not None"); Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1833,7 +1826,7 @@ if ((receiver == NULL) || (receiver == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL py_pool = make_ob_pool(pool); if (py_pool == NULL) { @@ -1868,7 +1861,7 @@ Py_DECREF(chpaths); Py_DECREF(py_pool); finished: - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1888,7 +1881,7 @@ if ((receiver == NULL) || (receiver == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(receiver, (char *) @@ -1905,7 +1898,7 @@ Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL return err; } @@ -1926,7 +1919,7 @@ if ((function == NULL) || (function == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"sslO&", @@ -1957,7 +1950,7 @@ } Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL *cred = creds; return err; } @@ -1977,7 +1970,7 @@ if ((function == NULL) || (function == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"slO&", @@ -2006,7 +1999,7 @@ } Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL *cred = creds; return err; } @@ -2030,7 +2023,7 @@ if ((function == NULL) || (function == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"slO&lO&", realm, failures, make_ob_auth_ssl_server_cert_info, @@ -2059,7 +2052,7 @@ Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL *cred = creds; return err; } @@ -2080,7 +2073,7 @@ if ((function == NULL) || (function == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"slO&", @@ -2110,7 +2103,7 @@ } Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL *cred = creds; return err; } @@ -2131,7 +2124,7 @@ if ((function == NULL) || (function == Py_None)) return SVN_NO_ERROR; - svn_swig_py_acquire_py_lock(); + SVN_SWIG_PY_BEGIN_PYTHON_CALL if ((result = PyObject_CallFunction(function, (char *)"slO&", @@ -2162,7 +2155,7 @@ } Py_DECREF(result); } - svn_swig_py_release_py_lock(); + SVN_SWIG_PY_END_PYTHON_CALL *cred = creds; return err; } Index: subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h =================================================================== --- subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h (revision 16776) +++ subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h (working copy) @@ -57,14 +57,6 @@ -/* Functions to manage python's global interpreter lock */ -SVN_SWIG_SWIGUTIL_EXPORT -void svn_swig_py_release_py_lock(void); - -SVN_SWIG_SWIGUTIL_EXPORT -void svn_swig_py_acquire_py_lock(void); - - /*** Automatic Pool Management Functions ***/ /* Set the application pool */ Index: subversion/bindings/swig/include/svn_types.swg =================================================================== --- subversion/bindings/swig/include/svn_types.swg (revision 16776) +++ subversion/bindings/swig/include/svn_types.swg (working copy) @@ -696,11 +696,11 @@ %exception { #ifdef SWIGPYTHON - svn_swig_py_release_py_lock(); + Py_BEGIN_ALLOW_THREADS #endif $action #ifdef SWIGPYTHON - svn_swig_py_acquire_py_lock(); + Py_END_ALLOW_THREADS #endif }