diff --git a/profiler/src/Demos/Samples.Computer01/ComputerService.cs b/profiler/src/Demos/Samples.Computer01/ComputerService.cs
index d51a9cff3974..07b51146409f 100644
--- a/profiler/src/Demos/Samples.Computer01/ComputerService.cs
+++ b/profiler/src/Demos/Samples.Computer01/ComputerService.cs
@@ -44,6 +44,7 @@ public class ComputerService
private NullThreadNameBugCheck _nullThreadNameBugCheck;
private MethodsSignature _methodsSignature;
private SigSegvHandlerExecution _sigsegvHandler;
+ private LinuxDlIteratePhdrDeadlock _linuxDlIteratePhdrDeadlock;
#if NET5_0_OR_GREATER
private OpenLdapCrash _openldapCrash;
@@ -181,6 +182,10 @@ public void StartService(Scenario scenario, int nbThreads, int parameter)
StartStringConcat(parameter);
break;
+ case Scenario.LinuxDlIteratePhdrDeadlock:
+ StartLinuxDlIteratePhdrDeadlock();
+ break;
+
default:
throw new ArgumentOutOfRangeException(nameof(scenario), $"Unsupported scenario #{_scenario}");
}
@@ -311,6 +316,10 @@ public void StopService()
case Scenario.StringConcat:
StopStringConcat();
break;
+
+ case Scenario.LinuxDlIteratePhdrDeadlock:
+ StopLinuxDlIteratePhdrDeadlock();
+ break;
}
}
@@ -575,6 +584,12 @@ private void StartLinuxMallocDeadlock()
_linuxMallockDeadlock.Start();
}
+ private void StartLinuxDlIteratePhdrDeadlock()
+ {
+ _linuxDlIteratePhdrDeadlock = new LinuxDlIteratePhdrDeadlock();
+ _linuxDlIteratePhdrDeadlock.Start();
+ }
+
private void StartMeasureAllocations()
{
_measureAllocations = new MeasureAllocations();
@@ -749,6 +764,11 @@ private void StopLinuxMallocDeadlock()
_linuxMallockDeadlock.Stop();
}
+ private void StopLinuxDlIteratePhdrDeadlock()
+ {
+ _linuxDlIteratePhdrDeadlock.Stop();
+ }
+
private void StopMeasureAllocations()
{
_measureAllocations.Stop();
diff --git a/profiler/src/Demos/Samples.Computer01/LinuxDlIteratePhdrDeadlock.cs b/profiler/src/Demos/Samples.Computer01/LinuxDlIteratePhdrDeadlock.cs
new file mode 100644
index 000000000000..3e9f9a077418
--- /dev/null
+++ b/profiler/src/Demos/Samples.Computer01/LinuxDlIteratePhdrDeadlock.cs
@@ -0,0 +1,124 @@
+//
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc.
+//
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Samples.Computer01
+{
+ internal class LinuxDlIteratePhdrDeadlock
+ {
+ private ManualResetEvent _stopEvent;
+ private Task _exceptionTask;
+ private Thread _worker;
+
+ public void Start()
+ {
+ if (_stopEvent != null)
+ {
+ throw new InvalidOperationException("Already running...");
+ }
+
+ _stopEvent = new ManualResetEvent(false);
+
+ _worker = new Thread(ExecuteCallToDlOpenDlClose)
+ {
+ IsBackground = false // set to false to prevent the app from shutting down. The test will fail
+ };
+ _worker.Start();
+
+ _exceptionTask = Task.Factory.StartNew(
+ () =>
+ {
+ var nbException = 0;
+ var loggingClock = Stopwatch.StartNew();
+ while (!IsEventSet())
+ {
+ if (loggingClock.ElapsedMilliseconds >= 1000)
+ {
+ Console.WriteLine($"* Nb thrown exception {nbException}");
+ Thread.Sleep(TimeSpan.FromMilliseconds(500));
+ nbException = 0;
+ loggingClock.Restart();
+ }
+
+ for (var i = 0; i < 20; i++)
+ {
+ try
+ {
+ throw new Exception("dl_iterate_phdr deadlock exception");
+ }
+ catch { }
+ nbException++;
+ }
+
+ // wait a bit randomly (23 is a prime number chosen randomly)
+ Thread.Sleep(TimeSpan.FromMilliseconds(23));
+ }
+ },
+ TaskCreationOptions.LongRunning);
+ }
+
+ public void Run()
+ {
+ Start();
+ Thread.Sleep(TimeSpan.FromSeconds(10));
+ Stop();
+ }
+
+ public void Stop()
+ {
+ if (_stopEvent == null)
+ {
+ throw new InvalidOperationException("Not running...");
+ }
+
+ _stopEvent.Set();
+
+ _worker.Join();
+ _exceptionTask.Wait();
+
+ _stopEvent.Dispose();
+ _stopEvent = null;
+ }
+
+ [DllImport("libdl.so", EntryPoint = "dlopen")]
+ private static extern IntPtr Dlopen(string filename, int flags);
+
+ [DllImport("libdl.so", EntryPoint = "dlclose")]
+ private static extern void DlClose(IntPtr handle);
+
+ private void ExecuteCallToDlOpenDlClose()
+ {
+ var loggingClock = Stopwatch.StartNew();
+ var counter = 0;
+
+ while (!IsEventSet())
+ {
+ if (loggingClock.ElapsedMilliseconds >= 1000)
+ {
+ Console.WriteLine($"* Nb execution {counter}");
+ Thread.Sleep(TimeSpan.FromMilliseconds(500));
+ counter = 0;
+ loggingClock.Restart();
+ }
+
+ var handle = Dlopen("libc.so.6", 2);
+ Thread.Sleep(TimeSpan.FromMilliseconds(10));
+ DlClose(handle);
+
+ counter++;
+ }
+ }
+
+ private bool IsEventSet()
+ {
+ return _stopEvent.WaitOne(0);
+ }
+ }
+}
diff --git a/profiler/src/Demos/Samples.Computer01/Program.cs b/profiler/src/Demos/Samples.Computer01/Program.cs
index 6a4f069fbc5f..7bbd13de7b3d 100644
--- a/profiler/src/Demos/Samples.Computer01/Program.cs
+++ b/profiler/src/Demos/Samples.Computer01/Program.cs
@@ -40,6 +40,7 @@ public enum Scenario
Obfuscation,
ThreadSpikes,
StringConcat, // parameter = number of strings to concatenate
+ LinuxDlIteratePhdrDeadlock,
}
public class Program
@@ -76,6 +77,7 @@ public static void Main(string[] args)
// 24: use an obfuscated library
// 25: create thread spikes
// 26: string concatenation
+ // 27: custom dl_iterate_phdr deadlock
//
Console.WriteLine($"{Environment.NewLine}Usage:{Environment.NewLine} > {Process.GetCurrentProcess().ProcessName} " +
$"[--service] [--iterations ] " +
diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/LinuxOnly/DlIteratePhdrDeadlock.cs b/profiler/test/Datadog.Profiler.IntegrationTests/LinuxOnly/DlIteratePhdrDeadlock.cs
new file mode 100644
index 000000000000..76be5a594e2d
--- /dev/null
+++ b/profiler/test/Datadog.Profiler.IntegrationTests/LinuxOnly/DlIteratePhdrDeadlock.cs
@@ -0,0 +1,31 @@
+//
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc.
+//
+
+using Datadog.Profiler.IntegrationTests.Helpers;
+using Datadog.Profiler.SmokeTests;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Datadog.Profiler.IntegrationTests.LinuxOnly
+{
+ [Trait("Category", "LinuxOnly")]
+ public class DlIteratePhdrDeadlock
+ {
+ private const string ScenarioLinuxDliteratePhdrDeadlock = "--scenario 27";
+ private readonly ITestOutputHelper _output;
+
+ public DlIteratePhdrDeadlock(ITestOutputHelper output)
+ {
+ _output = output;
+ }
+
+ [TestAppFact("Samples.Computer01")]
+ public void CheckApplicationDoesNotEndUpInDeadlock(string appName, string framework, string appAssembly)
+ {
+ var runner = new SmokeTestRunner(appName, framework, appAssembly, ScenarioLinuxDliteratePhdrDeadlock, _output);
+ runner.RunAndCheck();
+ }
+ }
+}