When test-web has completed running all tests there is a pending
DeferredInvoke in the main threads event queue. For Unix pthread, the
main threads event queue is leaked as the destructor callback in
pthread_key_create is not invoked. For Windows pthreads4w, the
destructor callback is invoked when the main thread is exiting. When
the main threads event queue is destroyed, the pending DeferredInvoke
event is destroyed which causes a leftover WebContentClient reference
to also get destroyed; however, the static WebContentClient::s_clients
HashTable has already been destroyed at this point, so we get a UAF in
the WebContentClient destructor and ASAN reports that error.
The reason why cleaning up the pending deferred invoke results in a
WebContentClient instance also being cleaned up is that class inherits
from IPC::ConnectionBase which is a Core::EventReceiver. The
deferred_invoke() method exposed on event receivers takes a strong
reference to itself to ensure it is still alive by the time the event
loop is ready to execute the function. There are a couple places in
IPC::ConnectionBase::drain_messages_from_peer() that utilized deferred
invocation which is why we have a leftover WebContentClient that has
past its useful lifetime at the end of TestWeb::run_tests().
Instead of holding onto a strong reference when the event has not yet
been processed, we take a weak reference and only grab a strong ref if
the receiver is alive when the event loop is about to execute our
function.