The first RegistrationOpen will run QuicLibraryLazyInitialize which allocates the worker pool. Parallel invocations of QuicLibraryLazyInitialize are serialized by a lock, and the first one to complete sets a flag indicating initialization is done before dropping the lock (library.c L938)
However, ExecutionCreate is not serialized against this same lock, and an incorrect program could race RegistrationOpen and ExecutionCreate so that ExecutionCreate runs just after the worker pool is allocated, but before the lazy initialization complete flag is set, and delete that worker pool (and mess up the source ref count tracking).
There are two solutions:
- This limitation needs to be documented so applications don't make this mistake.
- This needs to be prevented by waiting on the same lock before checking the flag.
I recommend the second option.