Skip to content

Commit d989a48

Browse files
committed
Add test for entering a natively created thread
1 parent d993fae commit d989a48

File tree

1 file changed

+43
-2
lines changed
  • graalpython/com.oracle.graal.python.test/src/tests/cpyext

1 file changed

+43
-2
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_thread.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -36,8 +36,9 @@
3636
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
39+
import threading
3940

40-
from . import CPyExtTestCase, CPyExtFunction, unhandled_error_compare
41+
from . import CPyExtTestCase, CPyExtFunction, unhandled_error_compare, CPyExtType
4142

4243
__dir__ = __file__.rpartition("/")[0]
4344

@@ -83,3 +84,43 @@ def compile_module(self, name):
8384
callfunction="test_PyThread_tss_functions",
8485
cmpfunc=unhandled_error_compare
8586
)
87+
88+
89+
class TestNativeThread:
90+
def test_register_new_thread(self):
91+
TestThread = CPyExtType(
92+
name="TestThread",
93+
includes="#include <pthread.h>",
94+
code=r'''
95+
void* thread_entrypoint(void* arg) {
96+
PyObject* callable = (PyObject*)arg;
97+
PyGILState_STATE gstate;
98+
gstate = PyGILState_Ensure();
99+
if (!PyObject_CallNoArgs(callable)) {
100+
PyErr_WriteUnraisable(callable);
101+
}
102+
PyGILState_Release(gstate);
103+
return NULL;
104+
}
105+
PyObject* run_in_thread(PyObject* self, PyObject* callable) {
106+
Py_BEGIN_ALLOW_THREADS;
107+
pthread_t thread;
108+
pthread_create(&thread, NULL, thread_entrypoint, callable);
109+
pthread_join(thread, NULL);
110+
Py_END_ALLOW_THREADS;
111+
Py_RETURN_NONE;
112+
}
113+
''',
114+
tp_methods='{"run_in_thread", (PyCFunction)run_in_thread, METH_O | METH_STATIC, ""}'
115+
)
116+
117+
thread = None
118+
119+
def callable():
120+
nonlocal thread
121+
thread = threading.current_thread()
122+
123+
TestThread.run_in_thread(callable)
124+
125+
assert thread
126+
assert thread is not threading.current_thread()

0 commit comments

Comments
 (0)