summaryrefslogtreecommitdiff
path: root/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs')
-rw-r--r--tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs77
1 files changed, 77 insertions, 0 deletions
diff --git a/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs b/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs
new file mode 100644
index 0000000000..0fda8172e4
--- /dev/null
+++ b/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using System.Threading;
+
+public class FinalizeTimeout
+{
+ public static int Main(string[] args)
+ {
+ Console.WriteLine("Main start");
+
+ // Run the finalizer at least once to have its code be jitted
+ BlockingFinalizerOnShutdown finalizableObject;
+ do
+ {
+ finalizableObject = new BlockingFinalizerOnShutdown();
+ } while (!BlockingFinalizerOnShutdown.finalizerCompletedOnce);
+
+ // Start a bunch of threads that allocate continuously, to increase the chance that when Main returns, one of the
+ // threads will be blocked for shutdown while holding one of the GC locks
+ for (int i = 0; i < Environment.ProcessorCount; ++i)
+ {
+ var t = new Thread(ThreadMain);
+ t.IsBackground = true;
+ t.Start();
+ }
+
+ // Wait a second to give the threads a chance to actually start running
+ Thread.Sleep(1000);
+
+ Console.WriteLine("Main end");
+
+ // Create another finalizable object, and immediately return from Main to have finalization occur during shutdown
+ finalizableObject = new BlockingFinalizerOnShutdown() { isLastObject = true };
+ return 100;
+ }
+
+ private static void ThreadMain()
+ {
+ byte[] b;
+ while (true)
+ b = new byte[1024];
+ }
+
+ private class BlockingFinalizerOnShutdown
+ {
+ public static bool finalizerCompletedOnce = false;
+ public bool isLastObject = false;
+
+ ~BlockingFinalizerOnShutdown()
+ {
+ if (finalizerCompletedOnce && !isLastObject)
+ return;
+
+ Console.WriteLine("Finalizer start");
+
+ // Allocate in the finalizer for long enough to try allocation after one of the background threads blocks for
+ // shutdown while holding one of the GC locks, to deadlock the finalizer. The main thread should eventually time
+ // out waiting for the finalizer thread to complete, and the process should exit cleanly.
+ TimeSpan timeout = isLastObject ? TimeSpan.FromMilliseconds(500) : TimeSpan.Zero;
+ TimeSpan elapsed = TimeSpan.Zero;
+ var start = DateTime.Now;
+ int i = -1;
+ object o;
+ do
+ {
+ o = new object();
+ } while ((++i & 0xff) != 0 || (elapsed = DateTime.Now - start) < timeout);
+
+ Console.WriteLine("Finalizer end");
+ finalizerCompletedOnce = true;
+ }
+ }
+}