@@ -2869,6 +2869,93 @@ PyDoc_STRVAR(docstring_with_signature_and_extra_newlines,
28692869"This docstring has a valid signature and some extra newlines."
28702870);
28712871
2872+ typedef struct {
2873+ PyThread_type_lock start_event ;
2874+ PyThread_type_lock exit_event ;
2875+ PyObject * callback ;
2876+ } test_c_thread_t ;
2877+
2878+ static void
2879+ temporary_c_thread (void * data )
2880+ {
2881+ test_c_thread_t * test_c_thread = data ;
2882+ PyGILState_STATE state ;
2883+ PyObject * res ;
2884+
2885+ PyThread_release_lock (test_c_thread -> start_event );
2886+
2887+ /* Allocate a Python thread state for this thread */
2888+ state = PyGILState_Ensure ();
2889+
2890+ res = PyObject_CallFunction (test_c_thread -> callback , "" , NULL );
2891+ Py_CLEAR (test_c_thread -> callback );
2892+
2893+ if (res == NULL ) {
2894+ PyErr_Print ();
2895+ }
2896+ else {
2897+ Py_DECREF (res );
2898+ }
2899+
2900+ /* Destroy the Python thread state for this thread */
2901+ PyGILState_Release (state );
2902+
2903+ PyThread_release_lock (test_c_thread -> exit_event );
2904+
2905+ PyThread_exit_thread ();
2906+ }
2907+
2908+ static PyObject *
2909+ call_in_temporary_c_thread (PyObject * self , PyObject * callback )
2910+ {
2911+ PyObject * res = NULL ;
2912+ test_c_thread_t test_c_thread ;
2913+ long thread ;
2914+
2915+ PyEval_InitThreads ();
2916+
2917+ test_c_thread .start_event = PyThread_allocate_lock ();
2918+ test_c_thread .exit_event = PyThread_allocate_lock ();
2919+ test_c_thread .callback = NULL ;
2920+ if (!test_c_thread .start_event || !test_c_thread .exit_event ) {
2921+ PyErr_SetString (PyExc_RuntimeError , "could not allocate lock" );
2922+ goto exit ;
2923+ }
2924+
2925+ Py_INCREF (callback );
2926+ test_c_thread .callback = callback ;
2927+
2928+ PyThread_acquire_lock (test_c_thread .start_event , 1 );
2929+ PyThread_acquire_lock (test_c_thread .exit_event , 1 );
2930+
2931+ thread = PyThread_start_new_thread (temporary_c_thread , & test_c_thread );
2932+ if (thread == -1 ) {
2933+ PyErr_SetString (PyExc_RuntimeError , "unable to start the thread" );
2934+ PyThread_release_lock (test_c_thread .start_event );
2935+ PyThread_release_lock (test_c_thread .exit_event );
2936+ goto exit ;
2937+ }
2938+
2939+ PyThread_acquire_lock (test_c_thread .start_event , 1 );
2940+ PyThread_release_lock (test_c_thread .start_event );
2941+
2942+ Py_BEGIN_ALLOW_THREADS
2943+ PyThread_acquire_lock (test_c_thread .exit_event , 1 );
2944+ PyThread_release_lock (test_c_thread .exit_event );
2945+ Py_END_ALLOW_THREADS
2946+
2947+ Py_INCREF (Py_None );
2948+ res = Py_None ;
2949+
2950+ exit :
2951+ Py_CLEAR (test_c_thread .callback );
2952+ if (test_c_thread .start_event )
2953+ PyThread_free_lock (test_c_thread .start_event );
2954+ if (test_c_thread .exit_event )
2955+ PyThread_free_lock (test_c_thread .exit_event );
2956+ return res ;
2957+ }
2958+
28722959static PyMethodDef TestMethods [] = {
28732960 {"raise_exception" , raise_exception , METH_VARARGS },
28742961 {"raise_memoryerror" , (PyCFunction )raise_memoryerror , METH_NOARGS },
@@ -2997,6 +3084,8 @@ static PyMethodDef TestMethods[] = {
29973084 {"docstring_with_signature_and_extra_newlines" ,
29983085 (PyCFunction )test_with_docstring , METH_NOARGS ,
29993086 docstring_with_signature_and_extra_newlines },
3087+ {"call_in_temporary_c_thread" , call_in_temporary_c_thread , METH_O ,
3088+ PyDoc_STR ("set_error_class(error_class) -> None" )},
30003089 {NULL , NULL } /* sentinel */
30013090};
30023091
0 commit comments