[fork] Entirely opt EE threads out of ExecCtx counting (#32536)

Follow-up to https://github.com/grpc/grpc/pull/32229.

https://github.com/grpc/grpc/pull/32229 incremented the `ExecCtx` count
unconditionally. It was previously impossible for a thread to exit
`IncExecCtxCount` while `fork_complete_` was `false`. These same threads
then went on to _decrement_ `count_` while the fork was still in
progress, putting `count_` well below its expected range ([0, 1] while
blocking and [2, inf) while not blocking). This resulted in cases where
`count_` would be stuck at a negative number with a thread infinitely
looping through `IncExecCtxCount`.

This PR instead opts EE threads out of ExecCtx counting entirely. They
handle clean-up of their threads separately through a separate set of
handlers registered by an entirely separate invocation of
`pthread_atfork`. This resolves the issue pointed out in [this
comment](https://github.com/grpc/grpc/issues/31885#issuecomment-1426445192).
pull/32549/head
Richard Belleville 2 years ago committed by GitHub
parent 27ee3913d1
commit c5213ceff9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/core/lib/gprpp/fork.cc

@ -67,7 +67,6 @@ class ExecCtxState {
// EventEngine is expected to terminate all threads before fork, and so this
// extra work is unnecessary
if (grpc_event_engine::experimental::ThreadLocal::IsEventEngineThread()) {
gpr_atm_no_barrier_fetch_add(&count_, 1);
return;
}
gpr_atm count = gpr_atm_no_barrier_load(&count_);
@ -89,7 +88,12 @@ class ExecCtxState {
}
}
void DecExecCtxCount() { gpr_atm_no_barrier_fetch_add(&count_, -1); }
void DecExecCtxCount() {
if (grpc_event_engine::experimental::ThreadLocal::IsEventEngineThread()) {
return;
}
gpr_atm_no_barrier_fetch_add(&count_, -1);
}
bool BlockExecCtx() {
// Assumes there is an active ExecCtx when this function is called

Loading…
Cancel
Save