From b0d6bf2a34d5e2e0cfb2410f58e768935d527be0 Mon Sep 17 00:00:00 2001
From: Ben Gamari <ben@smart-cactus.org>
Date: Tue, 18 Jun 2019 12:07:50 -0400
Subject: [PATCH] rts: Reset STATIC_LINK field of reverted CAFs

When we revert a CAF we must reset the STATIC_LINK field lest the GC
might ignore the CAF (e.g. as it carries the STATIC_FLAG_LIST flag) and
will consequently overlook references to object code that we are trying
to unload. This would result in the reachable object code being
unloaded. See Note [CAF lists] and Note [STATIC_LINK fields].

This fixes #16842.

Idea-due-to: Phuong Trinh <lolotp@fb.com>
---
 rts/sm/GCAux.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/rts/sm/GCAux.c b/rts/sm/GCAux.c
index 23ed3f0622f7..e8ca0c4002a0 100644
--- a/rts/sm/GCAux.c
+++ b/rts/sm/GCAux.c
@@ -114,16 +114,21 @@ isAlive(StgClosure *p)
 void
 revertCAFs( void )
 {
-    StgIndStatic *c;
+    StgIndStatic *c = revertible_caf_list;
 
-    for (c = revertible_caf_list;
-         c != (StgIndStatic *)END_OF_CAF_LIST;
-         c = (StgIndStatic *)c->static_link)
-    {
+    while (c != (StgIndStatic *) END_OF_CAF_LIST) {
         c = (StgIndStatic *)UNTAG_STATIC_LIST_PTR(c);
+        StgIndStatic *next = (StgIndStatic *) c->static_link;
+
         SET_INFO((StgClosure *)c, c->saved_info);
         c->saved_info = NULL;
-        // could, but not necessary: c->static_link = NULL;
+        // We must reset static_link lest the major GC finds that
+        // static_flag==3 and will consequently ignore references
+        // into code that we are trying to unload. This would result
+        // in reachable object code being unloaded prematurely.
+        // See #16842.
+        c->static_link = NULL;
+        c = next;
     }
     revertible_caf_list = (StgIndStatic*)END_OF_CAF_LIST;
 }
-- 
GitLab