|
|
|
# Background #
|
|
|
|
|
|
|
|
In Python, multithreading is ineffective at concurrency for CPU bound tasks
|
|
|
|
due to the GIL (global interpreter lock). Extension modules can release
|
|
|
|
the GIL in CPU bound tasks, but that isn't an option in pure Python.
|
|
|
|
Users use libraries such as multiprocessing, subprocess, concurrent.futures.ProcessPoolExecutor,
|
|
|
|
etc, to work around the GIL. These modules call ```fork()``` underneath the hood. Various issues have
|
|
|
|
been reported when using these modules with gRPC Python. gRPC Python wraps
|
|
|
|
gRPC core, which uses multithreading for performance, and hence doesn't support ```fork()```.
|
|
|
|
Historically, we didn't support forking in gRPC, but some users seemed
|
|
|
|
to be doing fine until their code started to break on version 1.6. This was
|
|
|
|
likely caused by the addition of background c-threads and a background
|
|
|
|
Python thread.
|
|
|
|
|
|
|
|
# Current Status #
|
|
|
|
|
|
|
|
## 1.11 ##
|
|
|
|
The background Python thread was removed entirely. This allows forking
|
|
|
|
after creating a channel. However, the channel must not have issued any
|
|
|
|
RPCs prior to the fork. Attempting to fork with an active channel that
|
|
|
|
has been used can result in deadlocks/corrupted wire data.
|
|
|
|
|
|
|
|
## 1.9 ##
|
|
|
|
A regression was noted in cases where users are doing fork/exec. This
|
|
|
|
was due to ```pthread_atfork()``` handler that was added in 1.7 to partially
|
|
|
|
support forking in gRPC. A deadlock can happen when pthread_atfork
|
|
|
|
handler is running, and an application thread is calling into gRPC.
|
|
|
|
We have provided a workaround for this issue by allowing users to turn
|
|
|
|
off the handler using env flag ```GRPC_ENABLE_FORK_SUPPORT=False```.
|
|
|
|
This should be set whenever a user expects to always call exec
|
|
|
|
immediately following fork. It will disable the fork handlers.
|
|
|
|
|
|
|
|
## 1.7 ##
|
|
|
|
A ```pthread_atfork()``` handler was added in 1.7 to automatically shut down
|
|
|
|
the background c-threads when fork was called. This does not shut down the
|
|
|
|
background Python thread, so users could not have any open channels when
|
|
|
|
forking.
|
|
|
|
|
|
|
|
# Future Work #
|
|
|
|
|
|
|
|
## 1.13 ##
|
|
|
|
The workaround when using fork/exec by setting
|
|
|
|
```GRPC_ENABLE_FORK_SUPPORT=False``` should no longer be needed. Following
|
|
|
|
[this PR](https://github.com/grpc/grpc/pull/14647), fork
|
|
|
|
handlers will not automatically run when multiple threads are calling
|
|
|
|
into gRPC.
|