question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Debug meta info not sent when using `PublishSingleFile=true`

See original GitHub issue

Package

Sentry

.NET Flavor

.NET

.NET Version

7.0.2013

OS

Any (not platform specific)

SDK Version

3.31.0

Steps to Reproduce

Create a simple console app:

using Sentry;

SentrySdk.Init(options =>
{
    options.Dsn = "...";
    options.Debug = true;
});

try
{
    throw new Exception("Test");
}
catch (Exception exception)
{
    SentrySdk.CaptureException(exception);
}

In the csproj, configure to upload symbols and sources to Sentry (and authenticate with sentry-cli login).

<PropertyGroup>
    <SentryOrg>...</SentryOrg>
    <SentryProject>...</SentryProject>
    <SentryUploadSymbols>true</SentryUploadSymbols>
    <SentryUploadSources>true</SentryUploadSources>
</PropertyGroup>

Compile and publish with:

dotnet publish -c Release -p:PublishSingleFile=true

Run the app from its published folder:

./bin/Release/net7.0/osx-arm64/publish/MyConsoleApp

Expected Result

The event generated and shown in the console debug output should contain a debug_meta section, including the debug_id.

In Sentry, the source context should be visible, and the debug images section should show the symbols were found.

Actual Result

The event is missing the debug_meta section when -p:PublishSingleFile=true is used. Thus, source context is not shown.

Line numbers will still be shown if the .pdb file is present (which it is by default in the publish folder), but if you delete it - or ship the executable app without the pdb file, then client-side symbolication won’t occur. Server-side symbolication also won’t occur because the debug_meta section is missing from the event.

Issue Analytics

  • State:closed
  • Created 4 months ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
jamescrosswellcommented, Jun 13, 2023

OK, ILSpy is cunning. Here’s what it’s doing:

Determine whether it’s a bundle

If it can’t load the assembly from a file, it then checks to see if it can load it from a bundle var bundle = LoadedPackage.FromBundle(fileName);

Basically it loads the whole package into into a MemoryMappedFile and then it hunts for a bundle signature in that memory stream. If it finds one, it can then return the bundleHeaderOffset which is what is used to lookup all the other bundle entries.

Get the other stuff in the bundle

Most of the work there happens in the SingleFileBundle.ReadManifest(Stream stream) method. It’s this that enumerates all of the entries (which include resource files being bundled with the single file executable, but also any bundled assemblies) with useful stuff like the offset, within the file/stream where that entry is kept.

Load details for specific entries/assemblies

In ILSpy at least, this happens when you try to expand the node representing an embedded assembly in the ILSpy UI. That’s where the PackageFolderTreeNode.LoadChildrenForFolder method gets invoked, and there’s some specific logic in there to handle dlls (I think folders are only relevant for resources - not for embedded assemblies).

This is where the offsets for bundled assemblies that were collected from the package manifest are used to load the bundled assemblies from memory - which happens in LoadedPackage.ResolveFileName(string name).

There’s a bit of inception going on at this point. The LoadedAssembly constructor is called. One of the parameters that gets passed in is Task.Run(entry.TryOpenStream)… In the case of bundled assemblies, the concrete implementaion of TryOpenStream that gets called is eventually BundleEntry.TryOpenStream. This method is critical as it’s where the logic to decompress bundles is implemented, if necessary. Otherwise, if the assembly hasn’t been bundled compressed, a plain vanilla UnmanagedMemoryStream gets returned starting at the appropriate entry offset.

Finally, once that Task completes and hands back a stream for the assembly we want, this gets used in the LoadedAssembly constructor in a call to LoadAsync… which is the same method that loaded our single file executable… only this time, the branch of code that gets executed is not that dealing with bundles but the one that loads vanilla assemblies from a memory stream.

Thankfully, ILSpy also has an MIT License… so it’d be OK to copy/reuse whichever bits of this logic were appropriate.

0reactions
mattjohnsonpintcommented, Jun 13, 2023

Sounds like we’re on the right path. Cool!

Thankfully, ILSpy also has an MIT License… so it’d be OK to copy/reuse whichever bits of this logic were appropriate.

If we are just learning from ILSpy and using the same approach, that’s fine. If you actually need to copy code from the ILSpy project, please put it in its own subdirectory and add an attribution file. For example, see /src/Sentry/Internal/FastSerialization - which is another bit of code we’ve internalized. Thanks.

Read more comments on GitHub >

github_iconTop Results From Across the Web

PublishSingleFile does not produce a single executable
I have a .Net Core 3 console application that i'm trying to publish as a self contained single executable. I've been able to...
Read more >
Create a single file for application deployment - .NET
On the Solution Explorer pane, right-click on the project you want to publish. Select Publish.
Read more >
Self-Contained Single-File does not produce a single file
I have a small .Net 5 console application with no dependencies on third party components. I have set it up to publish as...
Read more >
How to publish .NET console app to single independent . ...
I've tried "dotnet publish -r win-x64 --self-contained true" and many other combinations of options and they all produce a /bin folder with an...
Read more >
Ilyan. NET Framework. About; dotnet publish -c Release
1 is using different build process, not only via the "Build" button in VS, ... the publish step. dotnet publish -r win-x64 -p:PublishSingleFile=true...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found