Skip to content

Commit 734c569

Browse files
committed
rewrite fork handler into c - no python runtime required then
1 parent 20da5a0 commit 734c569

File tree

5 files changed

+33
-15
lines changed

5 files changed

+33
-15
lines changed

tests/test_process_spawning.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ def spawn_process():
9292
ctypes.c_size_t, ctypes.c_void_p)
9393
fread.restype = ctypes.c_size_t
9494

95-
for iteration in range(10000):
95+
for iteration in range(1000):
9696
t = Thread(target=run_echo,
9797
args=(popen, fread, pclose),
9898
daemon=True)
9999
t.start()
100-
t.join(timeout=20.0)
100+
t.join(timeout=10.0)
101101
if t.is_alive():
102102
raise Exception('process freeze detected at {}'
103103
.format(iteration))

uvloop/handles/process.pyx

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ cdef class UVProcess(UVHandle):
2828

2929
global __forking
3030
global __forking_loop
31+
global __forkHandler
3132

3233
cdef int err
3334

@@ -76,6 +77,7 @@ cdef class UVProcess(UVHandle):
7677
loop.active_process_handler = self
7778
__forking = 1
7879
__forking_loop = loop
80+
__forkHandler = <OnForkHandler>&__get_fork_handler
7981

8082
PyOS_BeforeFork()
8183

@@ -85,6 +87,7 @@ cdef class UVProcess(UVHandle):
8587

8688
__forking = 0
8789
__forking_loop = None
90+
__forkHandler = NULL
8891
loop.active_process_handler = None
8992

9093
PyOS_AfterFork_Parent()

uvloop/includes/fork_handler.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
typedef void (*OnForkHandler)();
3+
4+
OnForkHandler __forkHandler = NULL;
5+
6+
/* Auxiliary function to call global fork handler if defined.
7+
8+
Note: Fork handler needs to be in C (not cython) otherwise it would require
9+
GIL to be present, but some forks can exec non-python processes.
10+
*/
11+
void handleAtFork() {
12+
if (__forkHandler != NULL) {
13+
__forkHandler();
14+
}
15+
}

uvloop/includes/system.pxd

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ cdef extern from "unistd.h" nogil:
5959
void _exit(int status)
6060

6161

62-
cdef extern from "pthread.h" nogil:
62+
cdef extern from "pthread.h":
6363

6464
int pthread_atfork(
65-
void (*prepare)() nogil,
66-
void (*parent)() nogil,
67-
void (*child)() nogil)
65+
void (*prepare)(),
66+
void (*parent)(),
67+
void (*child)())
6868

6969

7070
cdef extern from "includes/compat.h" nogil:

uvloop/loop.pyx

+9-9
Original file line numberDiff line numberDiff line change
@@ -3117,21 +3117,21 @@ cdef vint __atfork_installed = 0
31173117
cdef vint __forking = 0
31183118
cdef Loop __forking_loop = None
31193119

3120+
cdef extern from "includes/fork_handler.h":
31203121

3121-
cdef void __atfork_child() nogil:
3122-
# See CPython/posixmodule.c for details
3123-
global __forking
3122+
ctypedef void (*OnForkHandler)()
3123+
cdef OnForkHandler __forkHandler
3124+
void handleAtFork()
31243125

3125-
if __forking:
3126-
__run_fork_handler()
3126+
cdef void __get_fork_handler() nogil:
3127+
global __forking
3128+
global __forking_loop
31273129

3128-
cdef void __run_fork_handler() nogil:
31293130
with gil:
3130-
if (__forking_loop is not None and
3131+
if (__forking and __forking_loop is not None and
31313132
__forking_loop.active_process_handler is not None):
31323133
__forking_loop.active_process_handler._after_fork()
31333134

3134-
31353135
cdef __install_atfork():
31363136
global __atfork_installed
31373137
if __atfork_installed:
@@ -3140,7 +3140,7 @@ cdef __install_atfork():
31403140

31413141
cdef int err
31423142

3143-
err = system.pthread_atfork(NULL, NULL, &__atfork_child)
3143+
err = system.pthread_atfork(NULL, NULL, &handleAtFork)
31443144
if err:
31453145
__atfork_installed = 0
31463146
raise convert_error(-err)

0 commit comments

Comments
 (0)