I guess the example is telling on an assumption on WaitableEvent's API which no longer holds - the magic apparently happens because event.signal() may be doing stuff to the event that no longer exists because wait()'s already finished and it’s scope ends there. Previously I guess the signal had the guarantee that as long as the object stays alive for the wait then it’ll be good.
Thanks for the example code, I was able to reproduce the hang and it seems that moving the notify_all() call inside the scope of the mutex fixes things. I’ve pushed this in f402a3f - can you see if it fixes the issue for you?