0

Is it possible in C#, running on a Windows server, to create a thread with a maximum stack size that is lower than 256KB? -- Or whatever the default is for IIS; or more specifically, an Azure Web Site.

This console program that I wrote seems to show that it's not possible through the .NET Thread constructor, and I haven't found any information on the web indicating that it's possible via P-Invoke or any other mechanisms.

Here's the program output on my Windows 10 desktop:

Default maximum stack size in bytes: 1,048,576
Expected maximum stack size in bytes: 64,000; Actual: 262,144
Expected maximum stack size in bytes: 128,000; Actual: 262,144
Expected maximum stack size in bytes: 512,000; Actual: 524,288
Expected maximum stack size in bytes: 2,048,000; Actual: 2,097,152
Expected maximum stack size in bytes: 1,024,000; Actual: 1,048,576

internal class Program
{
  public static void Main()
  {
    var threads = new[]
    {
      CreateControlThread(),
      CreateThread(64_000),
      CreateThread(128_000),
      CreateThread(512_000),
      CreateThread(1_024_000),
      CreateThread(2_048_000)
    };

    foreach (var thread in threads) thread.Start();
    foreach (var thread in threads) thread.Join();

    Console.ReadKey();
  }

  private Thread CreateControlThread()
     => new Thread(() => WriteMaximumStackSize(0));

  private static Thread CreateThread(int maximumStackSizeInBytes)
     => new Thread(() => WriteMaximumStackSize(maximumStackSizeInBytes), maximumStackSizeInBytes);

  private static void WriteMaximumStackSize(int expected)
  {
    GetCurrentThreadStackLimits(out uint low, out uint high);

    if (expected > 0)
    {
      Console.WriteLine("Expected maximum stack size in bytes: " + expected.ToString("n0") + "; Actual: " + (high - low).ToString("n0"));
    }
    else
    {
      Console.WriteLine("Default maximum stack size in bytes: " + (high - low).ToString("n0"));
    }
  }

  [DllImport("kernel32.dll")]
  private static extern void GetCurrentThreadStackLimits(out uint lowLimit, out uint highLimit);
}
Dave Sexton
  • 2,562
  • 1
  • 17
  • 26
  • 2
    Asking the obvious... Why do you want to do that? Take a look at: https://learn.microsoft.com/en-us/windows/desktop/ProcThread/thread-stack-size. – Flydog57 Oct 09 '18 at 02:33
  • Thanks for the link. It appears, then, that there's no way to set it strictly in C#. This is also interesting: "The operating system rounds up the specified size to the nearest multiple of the system's allocation granularity (typically 64 KB)". So 64KB would be the smallest I could go anyway. As for the "why" question, I can't provide details. Just rest assured that I'm not trying to do some clever optimization with my code, and it's not anything related to security. If you make your comment into an answer I'll mark it. – Dave Sexton Oct 09 '18 at 08:49
  • 1
    No, the CLR enforces a 256KB minimum. It matters, it isn't just used by your program. The jitter and the OS use it as well. Running out of space is always instantly fatal. – Hans Passant Oct 09 '18 at 14:09
  • Why the downvote? It's a perfectly reasonable question. Don't assume that I'm making a bad decision or that I don't understand the consequences of doing this just because I'm asking about it. – Dave Sexton Oct 09 '18 at 20:06
  • @HansPassant thanks for the answer, that explains it. My reason for being able to create a new thread (not pooled, not module-level) with less than 256KB is irrelevant. What's important to know is, it can't be done. Thanks again. – Dave Sexton Oct 09 '18 at 20:10
  • @HansPassant And btw your point, "running out of space is always instantly fatal" is actually the reason why I wanted to lower it. I know that's still somewhat cryptic, but you'll have to trust me that it's a VERY specific scenario. – Dave Sexton Oct 09 '18 at 20:12
  • Just do it the other way, allocate a lot of space before you run the critical code. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/stackalloc Not sharing kinda sucks btw, nobody learns anything from you and you don't get the answer you really need. – Hans Passant Oct 09 '18 at 20:15
  • Okay, so then here it is: It's not my code that will be executing. I need to limit the amount of resources that it can use. – Dave Sexton Oct 09 '18 at 20:23
  • Btw, my question was straight-forward, and you gave me the answer I really needed. "Why" is irrelevant :) – Dave Sexton Oct 09 '18 at 20:23

1 Answers1

0

Take a look at Thread Stack Size docs on Microsoft.com.

In particular, the default stack size is set in the PE Header (the header of the EXE file). You might possibly find a way to P/Invoke the appropriate calls to native thread creation calls that could manipulate the stack size, but I don't know how you'd attach a .NET Thread object to such a native thread.

There's no way that I can even imagine that you could do this for a thread pool thread.

You might look around for someone else's thread library. There may be something that suits your needs. I know that I've used third-party thread pool libraries successfully (but I don't remember any "bring your own thread" features).

Flydog57
  • 6,851
  • 2
  • 17
  • 18
  • Some additional info in the answers to [this question](https://stackoverflow.com/questions/5507574/maximum-thread-stack-size-net). – 500 - Internal Server Error Oct 09 '18 at 14:06
  • Hey, whoever downvoted me... I realize this isn't a very fully formed answer, but I put it there in response to the OP saying "If you make your comment into an answer I'll mark it". – Flydog57 Oct 09 '18 at 15:16
  • The answer is good enough. To be clear though, I'm not doing this for pooled threads or for the module at large. As per my question, I'm asking how to **create a new thread with a max stack size less than 256KB** – Dave Sexton Oct 09 '18 at 20:07