CNF: Silence pointer fix-up message unless gc debugging is enabled
[ghc.git] / rts / Weak.c
index 98ac760..f3e91fb 100644 (file)
@@ -39,15 +39,24 @@ runAllCFinalizers(StgWeak *list)
 
     task = myTask();
     if (task != NULL) {
-        task->running_finalizers = rtsTrue;
+        task->running_finalizers = true;
     }
 
     for (w = list; w; w = w->link) {
-       runCFinalizers((StgCFinalizerList *)w->cfinalizers);
+        // We need to filter out DEAD_WEAK objects, because it's not guaranteed
+        // that the list will not have them when shutting down.
+        // They only get filtered out during GC for the generation they
+        // belong to.
+        // If there's no major GC between the time that the finalizer for the
+        // object from the oldest generation is manually called and shutdown
+        // we end up running the same finalizer twice. See #7170.
+        if (w->header.info != &stg_DEAD_WEAK_info) {
+            runCFinalizers((StgCFinalizerList *)w->cfinalizers);
+        }
     }
 
     if (task != NULL) {
-        task->running_finalizers = rtsFalse;
+        task->running_finalizers = false;
     }
 }
 
@@ -73,41 +82,41 @@ scheduleFinalizers(Capability *cap, StgWeak *list)
     StgTSO *t;
     StgMutArrPtrs *arr;
     StgWord size;
-    nat n, i;
+    uint32_t n, i;
     Task *task;
 
     task = myTask();
     if (task != NULL) {
-        task->running_finalizers = rtsTrue;
+        task->running_finalizers = true;
     }
 
     // count number of finalizers, and kill all the weak pointers first...
     n = 0;
-    for (w = list; w; w = w->link) { 
-       // Better not be a DEAD_WEAK at this stage; the garbage
-       // collector removes DEAD_WEAKs from the weak pointer list.
-       ASSERT(w->header.info != &stg_DEAD_WEAK_info);
+    for (w = list; w; w = w->link) {
+        // Better not be a DEAD_WEAK at this stage; the garbage
+        // collector removes DEAD_WEAKs from the weak pointer list.
+        ASSERT(w->header.info != &stg_DEAD_WEAK_info);
 
-       if (w->finalizer != &stg_NO_FINALIZER_closure) {
-           n++;
-       }
+        if (w->finalizer != &stg_NO_FINALIZER_closure) {
+            n++;
+        }
 
-       runCFinalizers((StgCFinalizerList *)w->cfinalizers);
+        runCFinalizers((StgCFinalizerList *)w->cfinalizers);
 
-#ifdef PROFILING
+#if defined(PROFILING)
         // A weak pointer is inherently used, so we do not need to call
         // LDV_recordDead().
-       //
+        //
         // Furthermore, when PROFILING is turned on, dead weak
         // pointers are exactly as large as weak pointers, so there is
         // no need to fill the slop, either.  See stg_DEAD_WEAK_info
-        // in StgMiscClosures.hc.
+        // in StgMiscClosures.cmm.
 #endif
-       SET_HDR(w, &stg_DEAD_WEAK_info, w->header.prof.ccs);
+        SET_HDR(w, &stg_DEAD_WEAK_info, w->header.prof.ccs);
     }
-       
+
     if (task != NULL) {
-        task->running_finalizers = rtsFalse;
+        task->running_finalizers = false;
     }
 
     // No finalizers to run?
@@ -124,23 +133,23 @@ scheduleFinalizers(Capability *cap, StgWeak *list)
 
     n = 0;
     for (w = list; w; w = w->link) {
-       if (w->finalizer != &stg_NO_FINALIZER_closure) {
-           arr->payload[n] = w->finalizer;
-           n++;
-       }
+        if (w->finalizer != &stg_NO_FINALIZER_closure) {
+            arr->payload[n] = w->finalizer;
+            n++;
+        }
     }
     // set all the cards to 1
     for (i = n; i < size; i++) {
         arr->payload[i] = (StgClosure *)(W_)(-1);
     }
 
-    t = createIOThread(cap, 
-                      RtsFlags.GcFlags.initialStkSize, 
-                      rts_apply(cap,
-                          rts_apply(cap,
-                              (StgClosure *)runFinalizerBatch_closure,
-                              rts_mkInt(cap,n)), 
-                          (StgClosure *)arr)
-       );
+    t = createIOThread(cap,
+                       RtsFlags.GcFlags.initialStkSize,
+                       rts_apply(cap,
+                           rts_apply(cap,
+                               (StgClosure *)runFinalizerBatch_closure,
+                               rts_mkInt(cap,n)),
+                           (StgClosure *)arr)
+        );
     scheduleThread(cap,t);
 }