diff --git a/rts/IOManager.c b/rts/IOManager.c
index ee110d34f9037d9812ed8cc5cf430ea9c7c573fc..0c0b1819fcc8f964b77c5643d5a2af577ff1f112 100644
--- a/rts/IOManager.c
+++ b/rts/IOManager.c
@@ -480,6 +480,32 @@ void markCapabilityIOManager(evac_fn       evac,
 }
 
 
+void scavengeTSOIOManager(StgTSO *tso)
+{
+    switch (iomgr_type) {
+
+            /* case IO_MANAGER_SELECT:
+             * BlockedOn{Read,Write} uses block_info.fd
+             * BlockedOnDelay        uses block_info.target
+             * both of these are not GC pointers, so there is nothing to do.
+             */
+
+            /* case IO_MANAGER_WIN32_LEGACY:
+             * BlockedOn{Read,Write,DoProc} uses block_info.async_result
+             * The StgAsyncIOResult async_result is allocated on the C heap.
+             * It'd probably be better if it used the GC heap. If it did we'd
+             * scavenge it here.
+             */
+
+        default:
+            /* All the other I/O managers do not use I/O-related why_blocked
+             * reasons, so there are no cases to handle.
+             */
+            break;
+    }
+}
+
+
 /* Declared in rts/IOInterface.h. Used only by the MIO threaded I/O manager on
  * Unix platforms.
  */
diff --git a/rts/IOManager.h b/rts/IOManager.h
index 803960b0c23640a306340d70e6a70654ab3493e1..7d9b793e31c60861ae441ccf06114e840c01da87 100644
--- a/rts/IOManager.h
+++ b/rts/IOManager.h
@@ -272,6 +272,11 @@ void wakeupIOManager(void);
 void markCapabilityIOManager(evac_fn evac, void *user, CapIOManager *iomgr);
 
 
+/* GC hook: scavenge I/O related tso->block_info. Used by scavengeTSO.
+ */
+void scavengeTSOIOManager(StgTSO *tso);
+
+
 /* Several code paths are almost identical between read and write paths. In
  * such cases we use a shared code path with an enum to say which we're doing.
  */
diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c
index ca40a17632f5131e601b2e7e91aae238986c0225..59465e7bd185932b42a66434c63387e94126e37a 100644
--- a/rts/sm/Scav.c
+++ b/rts/sm/Scav.c
@@ -61,6 +61,7 @@
 #include "Trace.h"
 #include "Sanity.h"
 #include "Capability.h"
+#include "IOManager.h"
 #include "LdvProfile.h"
 #include "HeapUtils.h"
 #include "Hash.h"
@@ -145,6 +146,12 @@ scavengeTSO (StgTSO *tso)
     case NotBlocked:
         evacuate(&tso->block_info.closure);
         break;
+    case BlockedOnRead:
+    case BlockedOnWrite:
+    case BlockedOnDelay:
+    case BlockedOnDoProc:
+        scavengeTSOIOManager(tso);
+        break;
     default:
 #if defined(THREADED_RTS)
     // in the THREADED_RTS, block_info.closure must always point to a