Skip to content

SIGSEGV in netcoredbg when running on Linux with musl libc #103741

Open
@koorogi

Description

@koorogi

Description

Using netcoredbg (https://github.com/Samsung/netcoredbg) will crash with a segmentation fault when running on a musl-based Linux system.

Reproduction Steps

$ dotnet new console -o crash
The template "Console App" was created successfully.

Processing post-creation actions...
Restoring /home/koorogi/tmp/crash/crash/crash.csproj:
  Determining projects to restore...
  Restored /home/koorogi/tmp/crash/crash/crash.csproj (in 589 ms).
Restore succeeded.


$ cd crash
$ dotnet build
MSBuild version 17.8.5+b5265ef37 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  crash -> /home/koorogi/tmp/crash/crash/bin/Debug/net8.0/crash.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.73
$ netcoredbg
ncdb> file bin/Debug/net8.0/crash
ncdb> run
Segmentation fault

Expected behavior

Should be able to debug the program.

Actual behavior

The debugger crashes.

Regression?

No response

Known Workarounds

No response

Configuration

  • .NET 8.0.105
  • Gentoo Linux
  • Musl libc
  • x86_64

The issue is specific to the use of musl.

Other information

Backtrace from gdb:

(gdb) bt
#0  0x00007ffff72fd1f9 in EnsureStackSize (stackSize=1572864)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/pal/src/init/pal.cpp:266
#1  0x00007ffff72fcbe3 in Initialize (argc=argc@entry=1, argv=argv@entry=0x7ffff67b7f78, 
    flags=flags@entry=255)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/pal/src/init/pal.cpp:410
#2  0x00007ffff72fd35e in PAL_InitializeCoreCLR (
    szExePath=0x7ffff66333e0 "/usr/lib/netcoredbg/netcoredbg", runningInExe=<optimized out>)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/pal/src/init/pal.cpp:778
#3  0x00007ffff6e58b13 in coreclr_initialize (exePath=0x7ffff66333e0 "/usr/lib/netcoredbg/netcoredbg", 
    appDomainFriendlyName=appDomainFriendlyName@entry=0x5555556ecdea "debugger", 
    propertyCount=propertyCount@entry=5, propertyKeys=propertyKeys@entry=0x7ffff67b81a0, 
    propertyValues=propertyValues@entry=0x7ffff67b81e0, 
    hostHandle=hostHandle@entry=0x555555746c60 <netcoredbg::Interop::(anonymous namespace)::hostHandle>, 
    domainId=0x555555746c58 <netcoredbg::Interop::(anonymous namespace)::domainId>)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/dlls/mscoree/exports.cpp:275
#4  0x0000555555647baa in netcoredbg::Interop::Init (coreClrPath=...)
    at /usr/lib/gcc/x86_64-pc-linux-musl/14/include/g++-v14/bits/basic_string.h:227
#5  0x000055555561d2a0 in netcoredbg::ManagedCallback::CreateProcessW (this=0x7ffff67b9e90, 
    pProcess=0x7ffff7417b08)
    at /var/tmp/portage/dev-dotnet/netcoredbg-3.0.0.1018-r1/work/netcoredbg-3.0.0-1018/src/debugger/managedcallback.cpp:157
#6  0x00007ffff6b1006d in ShimProxyCallback::QueueCreateProcess(ICorDebugProcess*)::CreateProcessEvent::Dispatch(ManagedEvent::DispatchArgs) (this=0x7ffff7418b50, args=...)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/debug/di/shimcallback.cpp:350
#7  0x00007ffff6af93fe in CordbProcess::DispatchRCEvent (this=this@entry=0x7ffff7417ae0)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/debug/di/process.cpp:4701
#8  0x00007ffff6b025c8 in CordbRCEventThread::FlushQueuedEvents (this=this@entry=0x7ffff67c1460, 
    process=process@entry=0x7ffff7417ae0)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/debug/di/process.cpp:10296
#9  0x00007ffff6b02e6c in CordbRCEventThread::ThreadProc (this=0x7ffff67c1460)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/debug/di/process.cpp:10554
#10 0x00007ffff6b02f19 in CordbRCEventThread::ThreadProc (parameter=0x180000)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/debug/di/process.cpp:10620
#11 0x00007ffff69f44a0 in CorUnix::CPalThread::ThreadEntry (pvParam=0x7ffff67bf740)
    at /var/tmp/portage/dev-dotnet/dotnet-sdk-8.0.105/work/dotnet-sdk-8.0.5/src/runtime/artifacts/source-build/self/src/src/coreclr/pal/src/thread/thread.cpp:1760
#12 0x00007ffff7fb69ae in start (p=0x7ffff67b89b0) at src/thread/pthread_create.c:207
#13 0x00007ffff7fc48b5 in __clone () at src/thread/x86_64/clone.s:22
Backtrace stopped: frame did not save the PC

The crash occurs in EnsureStackSize, which simply allocates 1.5MB on the stack and tries to write to it to ensure there is enough stack space available.

Musl by default allocates smaller thread stack sizes than glibc does, but that's actually not the root issue in this case. This thread was created by .NET itself, and a fixed stack size (larger than the musl default) is requested when the thread is created.

The value of g_defaultStackSize which determines the requested stack size is set to a fixed value of 1.5MB on musl.

This same size (g_defaultStackSize) is what is passed to EnsureStackSize.

So, a thread is created with a 1.5MB stack, and 13 stack frames deep, the code tries to verify that 1.5MB is still available on the stack, and it isn't because those 13 stack frames have already used some of it.

Based on #9855 (comment), it sounds like EnsureStackSize is only intended to be used on the main thread, but the code that ensures this assumes that Initialize is called on the main thread, and that doesn't seem to be the case here.

I don't know if netcoredbg is doing something wrong by calling into Initialize from a different thread, but it looks like the thread where this call is happening is the CordbRCEventThread::ThreadProc thread.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions