@@ -30,6 +30,7 @@ private static void FullGCCollect()
3030 {
3131 GC . Collect ( ) ;
3232 GC . WaitForPendingFinalizers ( ) ;
33+ GC . Collect ( ) ; // reclaim objects whose finalizers just ran
3334 }
3435
3536 [ Test ]
@@ -51,28 +52,28 @@ public void CollectBasicObject()
5152 Finalizer . Instance . BeforeCollect += handler ;
5253
5354 IntPtr pyObj = MakeAGarbage ( out var shortWeak , out var longWeak ) ;
54- FullGCCollect ( ) ;
55- // The object has been resurrected
56- Warn . If (
57- shortWeak . IsAlive ,
58- "The referenced object is alive although it should have been collected" ,
59- shortWeak
60- ) ;
61- Assert . That (
62- longWeak . IsAlive ,
63- Is . True ,
64- $ "The reference object is not alive although it should still be"
65- ) ;
6655
56+ // The real contract: after the wrapper is GC'd, the underlying
57+ // Python pointer must end up in Finalizer's queue. Poll because
58+ // .NET Framework / .NET Core differ in how many GC cycles it takes.
59+ List < IntPtr > garbage = null ;
60+ for ( int attempt = 0 ; attempt < 10 ; attempt ++ )
6761 {
68- var garbage = Finalizer . Instance . GetCollectedObjects ( ) ;
69- Assert . NotZero ( garbage . Count , "There should still be garbage around" ) ;
70- Warn . Unless (
71- garbage . Contains ( pyObj ) ,
72- $ "The { nameof ( longWeak ) } reference doesn't show up in the garbage list",
73- garbage
74- ) ;
62+ FullGCCollect ( ) ;
63+ garbage = Finalizer . Instance . GetCollectedObjects ( ) ;
64+ if ( garbage . Contains ( pyObj ) ) break ;
65+ Thread . Sleep ( 20 ) ;
7566 }
67+
68+ Warn . If ( shortWeak . IsAlive ,
69+ "shortWeak is alive after FullGCCollect; runtime hasn't reclaimed the wrapper yet" ,
70+ shortWeak ) ;
71+ // longWeak.IsAlive at this point is .NET-GC-implementation-defined
72+ // (Framework reclaims post-finalize objects more eagerly than Core);
73+ // intentionally not asserted.
74+
75+ Assert . That ( garbage , Has . Member ( pyObj ) ,
76+ "PyObject did not reach Finalizer.Instance.GetCollectedObjects()" ) ;
7677 try
7778 {
7879 Finalizer . Instance . Collect ( ) ;
0 commit comments