Skip to content

Commit 7b6b423

Browse files
committed
Add ping mechanism for .NET crashtracker
1 parent 37f6383 commit 7b6b423

File tree

5 files changed

+117
-8
lines changed

5 files changed

+117
-8
lines changed

profiler/src/ProfilerEngine/Datadog.Profiler.Native/CrashReporting.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,31 @@ int32_t CrashReporting::Send()
337337
return ExportImpl(nullptr);
338338
}
339339

340+
int32_t CrashReporting::SendPing()
341+
{
342+
return SendPingImpl(nullptr);
343+
}
344+
340345
int32_t CrashReporting::WriteToFile(const char* url)
341346
{
342347
auto endpoint = ddog_endpoint_from_url(libdatadog::to_char_slice(url));
343348
on_leave { if (endpoint != nullptr) ddog_endpoint_drop(endpoint); };
344349
return ExportImpl(endpoint);
345350
}
346351

352+
int32_t CrashReporting::WritePingToFile(const char* url)
353+
{
354+
auto endpoint = ddog_endpoint_from_url(libdatadog::to_char_slice(url));
355+
on_leave { if (endpoint != nullptr) ddog_endpoint_drop(endpoint); };
356+
return SendPingImpl(endpoint);
357+
}
358+
359+
int32_t CrashReporting::SendPingImpl(ddog_Endpoint* endpoint)
360+
{
361+
CHECK_RESULT(ddog_crasht_CrashInfoBuilder_upload_ping_to_endpoint(&_builder, endpoint));
362+
return 0;
363+
}
364+
347365
int32_t CrashReporting::ExportImpl(ddog_Endpoint* endpoint)
348366
{
349367
// _builder.inner will be claimed by the Rust API. No need to call XX_drop.

profiler/src/ProfilerEngine/Datadog.Profiler.Native/CrashReporting.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ ICrashReporting : public IUnknown
109109
virtual int32_t STDMETHODCALLTYPE ResolveStacks(int32_t crashingThreadId, ResolveManagedCallstack resolveCallback, void* context, bool* isSuspicious) = 0;
110110
virtual int32_t STDMETHODCALLTYPE SetMetadata(const char* libraryName, const char* libraryVersion, const char* family, Tag* tags, int32_t tagCount) = 0;
111111
virtual int32_t STDMETHODCALLTYPE Send() = 0;
112+
virtual int32_t STDMETHODCALLTYPE SendPing() = 0;
112113
virtual int32_t STDMETHODCALLTYPE WriteToFile(const char* url) = 0;
114+
virtual int32_t STDMETHODCALLTYPE WritePingToFile(const char* url) = 0;
113115
virtual int32_t STDMETHODCALLTYPE CrashProcess() = 0;
114116
};
115117

@@ -131,7 +133,9 @@ class CrashReporting : public ICrashReporting
131133
int32_t STDMETHODCALLTYPE ResolveStacks(int32_t crashingThreadId, ResolveManagedCallstack resolveCallback, void* context, bool* isSuspicious) override;
132134
int32_t STDMETHODCALLTYPE SetMetadata(const char* libraryName, const char* libraryVersion, const char* family, Tag* tags, int32_t tagCount) override;
133135
int32_t STDMETHODCALLTYPE Send() override;
136+
int32_t STDMETHODCALLTYPE SendPing() override;
134137
int32_t STDMETHODCALLTYPE WriteToFile(const char* url) override;
138+
int32_t STDMETHODCALLTYPE WritePingToFile(const char* url) override;
135139
int32_t STDMETHODCALLTYPE CrashProcess() override;
136140

137141
protected:
@@ -150,6 +154,7 @@ class CrashReporting : public ICrashReporting
150154
static std::vector<StackFrame> MergeFrames(const std::vector<StackFrame>& nativeFrames, const std::vector<StackFrame>& managedFrames);
151155
private:
152156
int32_t ExportImpl(ddog_Endpoint* endpoint);
157+
int32_t SendPingImpl(ddog_Endpoint* endpoint);
153158

154159
template <typename T>
155160
std::pair<decltype(T::ok), bool> ExtractResult(T v);

tracer/src/Datadog.Trace.Tools.dd_dotnet/CreatedumpCommand.cs

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,15 @@ private unsafe void GenerateCrashReport(int pid, int? signal, int? crashThread)
602602
}
603603
}
604604

605+
// Set signal information early to include it in the ping
606+
if (signal.HasValue)
607+
{
608+
DebugPrint("Adding signal information to the crash report");
609+
_ = SetSignal(crashReport, signal.Value);
610+
}
611+
612+
_ = SendPing(crashReport, _runtime);
613+
605614
if (crashThread == null)
606615
{
607616
var firstThreadWithException = _runtime.Threads.FirstOrDefault(t => t.CurrentException != null);
@@ -707,12 +716,6 @@ private unsafe void GenerateCrashReport(int pid, int? signal, int? crashThread)
707716
AnsiConsole.WriteLine("Datadog - The crash may have been caused by automatic instrumentation, sending crash report...");
708717
}
709718

710-
if (signal.HasValue)
711-
{
712-
DebugPrint("Adding signal information to the crash report");
713-
_ = SetSignal(crashReport, signal.Value);
714-
}
715-
716719
DebugPrint("Setting crash report metadata");
717720
_ = SetMetadata(crashReport, _runtime, exception, isSuspicious);
718721

@@ -810,6 +813,65 @@ private bool SetSignal(ICrashReport crashReport, int signal)
810813
return true;
811814
}
812815

816+
private unsafe bool SendPing(ICrashReport crashReport, ClrRuntime runtime)
817+
{
818+
DebugPrint("Sending crash ping");
819+
if (!SetMetadata(crashReport, runtime, null, false))
820+
{
821+
AddError("Failed to set metadata for ping");
822+
return false;
823+
}
824+
825+
try
826+
{
827+
var outputFile = Environment.GetEnvironmentVariable(EnvironmentOutput);
828+
829+
if (!string.IsNullOrEmpty(outputFile))
830+
{
831+
var path = IntPtr.Zero;
832+
833+
try
834+
{
835+
var filename = Path.GetFileNameWithoutExtension(outputFile);
836+
var directory = Path.GetDirectoryName(outputFile);
837+
var pingFile = $"{filename}-ping.json";
838+
if (directory == null)
839+
{
840+
outputFile = pingFile;
841+
}
842+
else
843+
{
844+
outputFile = Path.Combine(directory, pingFile);
845+
}
846+
847+
DebugPrint($"Writing crash ping to {outputFile}...");
848+
path = Marshal.StringToHGlobalAnsi(outputFile);
849+
crashReport.WritePingToFile(path);
850+
}
851+
finally
852+
{
853+
if (path != IntPtr.Zero)
854+
{
855+
Marshal.FreeHGlobal(path);
856+
}
857+
}
858+
}
859+
else
860+
{
861+
DebugPrint("Sending crash report");
862+
crashReport.SendPing();
863+
}
864+
}
865+
catch (Win32Exception ex)
866+
{
867+
AddError($"Failed to send ping: {GetLastError(crashReport, ex)}");
868+
return false;
869+
}
870+
871+
DebugPrint("Crash ping sent successfully");
872+
return true;
873+
}
874+
813875
private unsafe bool SetMetadata(ICrashReport crashReport, ClrRuntime runtime, ClrException? exception, bool isSuspicious)
814876
{
815877
var flavor = runtime.ClrInfo.Flavor switch

tracer/src/Datadog.Trace.Tools.dd_dotnet/Generated/Datadog.Trace.Tools.dd_dotnet.SourceGenerators/NativeObjectsGenerator/dd_dotnet.ICrashReport.g.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,29 @@ public int Send()
126126
}
127127
return returnvalue;
128128
}
129+
public int SendPing()
130+
{
131+
var func = (delegate* unmanaged[Stdcall]<IntPtr, out int, int>)*(VTable + 10);
132+
var result = func(_implementation, out var returnvalue);
133+
if (result != 0)
134+
{
135+
throw new System.ComponentModel.Win32Exception(result);
136+
}
137+
return returnvalue;
138+
}
129139
public int WriteToFile(nint a0)
130140
{
131-
var func = (delegate* unmanaged[Stdcall]<IntPtr, nint, out int, int>)*(VTable + 10);
141+
var func = (delegate* unmanaged[Stdcall]<IntPtr, nint, out int, int>)*(VTable + 11);
142+
var result = func(_implementation, a0, out var returnvalue);
143+
if (result != 0)
144+
{
145+
throw new System.ComponentModel.Win32Exception(result);
146+
}
147+
return returnvalue;
148+
}
149+
public int WritePingToFile(nint a0)
150+
{
151+
var func = (delegate* unmanaged[Stdcall]<IntPtr, nint, out int, int>)*(VTable + 12);
132152
var result = func(_implementation, a0, out var returnvalue);
133153
if (result != 0)
134154
{
@@ -138,7 +158,7 @@ public int WriteToFile(nint a0)
138158
}
139159
public int CrashProcess()
140160
{
141-
var func = (delegate* unmanaged[Stdcall]<IntPtr, out int, int>)*(VTable + 11);
161+
var func = (delegate* unmanaged[Stdcall]<IntPtr, out int, int>)*(VTable + 13);
142162
var result = func(_implementation, out var returnvalue);
143163
if (result != 0)
144164
{

tracer/src/Datadog.Trace.Tools.dd_dotnet/ICrashReport.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ internal unsafe interface ICrashReport : IUnknown
3131

3232
int Send();
3333

34+
int SendPing();
35+
3436
int WriteToFile(IntPtr url);
3537

38+
int WritePingToFile(IntPtr url);
39+
3640
[Obsolete("You're aware it's going to crash the process, right?")]
3741
int CrashProcess();
3842

0 commit comments

Comments
 (0)