Use-after-free in compact gc with poll I/O manager
there is a use-after-free issue in compact gc caught by !15168 by running `./hadrian/build --flavour=quick-validate+debug_info+ubsan+asan --docs=none -j test runtest.opts+=--way=compacting_gc --only=hGetBuf001`:
```
Stderr run ( hGetBuf001 ):
=================================================================
==3558730==ERROR: AddressSanitizer: use-after-poison on address 0x7eb52a3fd718 at pc 0x000000904560 bp 0x7ffe63c2b080 sp 0x7ffe63c2b070
READ of size 8 at 0x7eb52a3fd718 thread T0
#0 0x90455f in deleteTimeoutQueue rts/TimeoutQueue.c:262
#1 0x901e40 in syncDelayCancelTimeout rts/posix/Timeout.c:68
#2 0x7ce972 in removeFromQueues rts/RaiseAsync.c:716
#3 0x7d339e in throwToSingleThreaded__ rts/RaiseAsync.c:66
#4 0x7d339e in throwToSingleThreaded__ rts/RaiseAsync.c:57
#5 0x7d339e in throwToSingleThreaded rts/RaiseAsync.c:74
#6 0x7c207a in deleteThread rts/Schedule.c:2946
#7 0x7c207a in deleteThread rts/Schedule.c:2937
#8 0x7c207a in deleteAllThreads rts/Schedule.c:2422
#9 0x7c207a in scheduleDoGC rts/Schedule.c:1856
#10 0x7c4730 in exitScheduler rts/Schedule.c:2811
#11 0x7a0319 in hs_exit_ rts/RtsStartup.c:498
#12 0x7a0319 in hs_exit_ rts/RtsStartup.c:465
#13 0x7a2385 in shutdownHaskellAndExit rts/RtsStartup.c:686
#14 0x72848a in hs_main rts/RtsMain.c:104
#15 0x2a86ad in main (/tmp/ghctest-sqc0nmsx/test spaces/libraries/base/tests/IO/hGetBuf001.run/hGetBuf001+0x2a86ad) (BuildId: 3528405b41c11eefd980a270f4a2cea20fc9b987)
#16 0x7fb52e0201c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#17 0x7fb52e02028a in __libc_start_main_impl ../csu/libc-start.c:360
#18 0x29e024 in _start (/tmp/ghctest-sqc0nmsx/test spaces/libraries/base/tests/IO/hGetBuf001.run/hGetBuf001+0x29e024) (BuildId: 3528405b41c11eefd980a270f4a2cea20fc9b987)
Address 0x7eb52a3fd718 is a wild pointer inside of access range of size 0x000000000008.
SUMMARY: AddressSanitizer: use-after-poison rts/TimeoutQueue.c:262 in deleteTimeoutQueue
Shadow bytes around the buggy address:
0x7eb52a3fd480: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd500: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd580: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd600: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd680: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
=>0x7eb52a3fd700: f7 f7 f7[f7]f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd780: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd800: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd880: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd900: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x7eb52a3fd980: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
```
during rts shutdown, `deleteTimeoutQueue` is loading from an `StgTimeout` closure with ASAN poisoned payload, and from the shadow bytes around it, it seems to be a whole poisoned block in the block allocator, so the closure is garbage collected and it's a use-after-free issue.
the real underlying issue is the compact gc didn't properly thread the `tso->block_info` closure in some cases where it's written by the poll I/O manager (as `StgAsyncIOOp` or `StgTimeout` closure), so `tso->block_info` was not threaded in `thread_TSO`.
issue