We already have interceptors for dispatch_source API (e.g. dispatch_source_set_event_handler), but they currently only handle submission synchronization. We also need to synchronize based on the target queue (serial, concurrent), in other words, we need to use dispatch_callback_wrap. This patch implements that.
However, some more magic is needed for this to work, because the callback set in dispatch_source_set_event_handler is called multiple times (to the contrary of most other GCD APIs), so we cannot free() the context in the callback. The lifetime of the context and the wrapper block needs to be inherited from the outer block (the one actually submitted to REAL(dispatch_source_set_event_handler)), so we need to *capture* the original handler *and* the context. The Block_copy is needed to make sure the __block tsan_block_context_t new_context is converted to a heap-allocated object.