diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c58cb7c4..86078e4f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -406,6 +406,7 @@ if (NOT PYZMQ_BACKEND) set(PYZMQ_BACKEND "cffi") else() set(PYZMQ_BACKEND "cython") + add_compile_definitions(CYTHON_USE_MODULE_STATE=1) endif() endif() diff --git a/tests/test_subshell.py b/tests/test_subshell.py new file mode 100644 index 000000000..8bbd7d9a8 --- /dev/null +++ b/tests/test_subshell.py @@ -0,0 +1,36 @@ +import sys + +import pytest +from conftest import recv + +import zmq + +if sys.version_info < (3, 14): + pytest.skip("Requires Python 3.14") + +from concurrent.futures import InterpreterPoolExecutor + + +def echo(url): + with zmq.Context() as ctx, ctx.socket(zmq.ROUTER) as s: + s.bind(url) + msg = s.recv_multipart() + print(msg) + + +def test_subshell(context, socket): + s = socket(zmq.DEALER) + url = "tcp://127.0.0.1:5555" + with InterpreterPoolExecutor(1) as pool: + f = pool.submit(echo, url) + try: + f.result(timeout=1) + except TimeoutError: + pass + else: + pytest.fail("echo task exited prematurely...") + s.connect(url) + msg = b"msg" + s.send(msg) + recvd = recv(s) + assert recvd == msg diff --git a/zmq/backend/cython/_zmq.py b/zmq/backend/cython/_zmq.py index c6f53a540..9644ee504 100644 --- a/zmq/backend/cython/_zmq.py +++ b/zmq/backend/cython/_zmq.py @@ -1,5 +1,7 @@ # cython: language_level = 3str # cython: freethreading_compatible = True +# cython: subinterpreters_compatible = own_gil + """Cython backend for pyzmq""" # Copyright (C) PyZMQ Developers @@ -49,6 +51,7 @@ cfunc, char, declare, + exceptval, inline, nogil, p_char, @@ -169,7 +172,7 @@ @cfunc @inline -@C.exceptval(-1) +@exceptval(-1) def _check_rc(rc: C.int, error_without_errno: bint = False) -> C.int: """internal utility for checking zmq return condition @@ -1804,6 +1807,7 @@ def proxy_steerable( @cfunc @inline @nogil +@exceptval(check=False) def _mq_relay( in_socket: p_void, out_socket: p_void, @@ -1887,6 +1891,7 @@ def _mq_relay( @cfunc @inline @nogil +@exceptval(check=False) def _mq_inline( in_socket: p_void, out_socket: p_void,