rts: Reset STATIC_LINK field of reverted CAFs
authorBen Gamari <ben@smart-cactus.org>
Tue, 18 Jun 2019 16:07:50 +0000 (12:07 -0400)
committerBen Gamari <ben@smart-cactus.org>
Wed, 26 Jun 2019 17:46:33 +0000 (13:46 -0400)
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>
(cherry picked from commit 2a960c3a04afcfcdb25a13e9a6e65c94c22a169f)

rts/sm/GCAux.c

index 23ed3f0..e8ca0c4 100644 (file)
@@ -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;
 }