revocation: Synchronize CRL fetches of multiple threads to the same URL
When handling many connection attempts from peers using the same CA, a slow
or non-responsive CRL distribution point can lead to concurrent fetches of
the same CRL by multiple threads. This is not only inefficient, but results
in all threads blocking for the full fetch timeout, potentially blocking
all threads in the pool.
As a first step, synchronize CRL fetches using a global mutex and a per-URL
condvar, so threads can wait for the CRL if another is already fetching it.
This reduces the number of useless concurrent CRL fetches, and allows threads
joining the party late to get blocked only until the first fetch completes
or times out.
The URL entry is preserved in the hashtable after completing the fetch.
This will allow subsequent optimizations to store the last fetch result
and act accordingly. The CRL itself is not, as CRLs can be rather large
and caching them can be done using existing mechanisms controlled via
corresponding options.