dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.98k stars 4.66k forks source link

mono_thread_platform_create_thread crashing with pthread_attr_setstacksize invalid argument error #105490

Open stephentoub opened 1 month ago

stephentoub commented 1 month ago

Mono does not round up the argument to pthread_attr_setstacksize to the platform virtual page size which results in an EINVAL which will cause new Thread(ThreadStart, Int32) to fail


https://github.com/dotnet/runtime/pull/105445#issuecomment-2249344552

The osx-x64 Debug Mono_MiniJIT_LibrariesTests leg crashed with:

mono_thread_platform_create_thread: pthread_attr_setstacksize failed, error: "Invalid argument" (22)

when trying to set a maxStackSize on a new thread to 100_000.

lambdageek commented 1 month ago

I think this is because we're not aligning the requested stakc size to a multiple of the page size

compare Mono

https://github.com/dotnet/runtime/blob/1d27457dd6dad96226c22cbafe1653fa98480fd3/src/mono/mono/utils/mono-threads-posix.c#L60-L80

to coreCLR PAL

https://github.com/dotnet/runtime/blob/1d27457dd6dad96226c22cbafe1653fa98480fd3/src/coreclr/pal/src/thread/thread.cpp#L550-L565

lambdageek commented 1 month ago

/cc @steveisok

EgorBo commented 1 month ago

@lambdageek I am not sure if that is related, but we also bumped default thread stack size on macOS for CoreCLR, from 512kb (which is fairly low) to 1 or 2 mb.

Since mac has 8mb for mainthread and 512kb for all secondary threads by default (on system level)

lambdageek commented 1 month ago

limits.h in the MacOSX.sdk has

#if defined(__arm__) || defined(__arm64__)
#define PTHREAD_STACK_MIN       16384
#else
#define PTHREAD_STACK_MIN       8192
#endif

So requesting something smaller than the default ought to work. Mono does have a check that we ask for at least PTHREAD_STACK_MIN even if the user specified something smaller.

lambdageek commented 1 month ago

Not a recent regression, btw. The following fails on mono going back to net6.0 at least (and probably older)

using System.Threading;

public class Program
{
    public static void Main()
    {
        var t = new Thread(() => {
            Console.WriteLine ("from a new thread");
            }, 16384 + 1);
        t.Start();
        t.Join();
    }
}
lambdageek commented 1 month ago

DeepEquals_TooDeepJsonDocument_ThrowsInsufficientExecutionStackException was updated to use a multiple of 64k for the stack size. So there's no disabled test anymore; it's just about aligning behavior now