fix use-after-free: broadcast() was destroying consumers still referenced by Handler
broadcast() removed dead consumers from the list AND called shutdown()+destroy(),
but Handler.close() still held the pointer and later called removeConsumer() on
freed memory. Now broadcast() only unlinks from the list — removeConsumer() is
the sole owner of shutdown + destroy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>