[Bug libc/23018] New: pthread_create reserves less stack space than requested without failing on linux-arm64

kouvel at outlook dot com sourceware-bugzilla@sourceware.org
Thu Mar 29 20:21:00 GMT 2018


https://sourceware.org/bugzilla/show_bug.cgi?id=23018

            Bug ID: 23018
           Summary: pthread_create reserves less stack space than
                    requested without failing on linux-arm64
           Product: glibc
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: kouvel at outlook dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---

From issue reported at https://github.com/dotnet/coreclr/issues/17170 by
https://github.com/sdmaclea

Test case:

----------------------------------------------

#include <unistd.h>
#include <errno.h>
#include <string.h>

#include <pthread.h>

#include <iostream>
using namespace std;

void PrintError(int error)
{
    const char *errorName = "?";
    switch(error)
    {
        case ENOMEM:
            errorName = "ENOMEM";
            break;
        case EINVAL:
            errorName = "EINVAL";
            break;
        case EAGAIN:
            errorName = "EAGAIN";
            break;
        case EPERM:
            errorName = "EPERM";
            break;
        default:
            break;
    }
    cout << errorName << " (" << error << ')';
}

bool CheckAndPrintErrorOnNonzero(const char *op, int error)
{
    if(error == 0)
        return true;
    cout << op << " failed: ";
    PrintError(error);
    cout << '\n';
    return false;
}

size_t requestedStackSize = 16 << 20;

void *ThreadStart(void *)
{
    char a[requestedStackSize - (64 << 10)];
    memset(a, 0, sizeof(a));
    return nullptr;
}

int main()
{
    pthread_attr_t attr;
    int error = pthread_attr_init(&attr);
    if(!CheckAndPrintErrorOnNonzero("attr_init", error))
        return 0;

    error = pthread_attr_setstacksize(&attr, requestedStackSize);
    if(!CheckAndPrintErrorOnNonzero("attr_setstacksize", error))
        return 0;

    pthread_t thread;
    error = pthread_create(&thread, &attr, &ThreadStart, nullptr);
    if(!CheckAndPrintErrorOnNonzero("create", error))
        return 0;

    error = pthread_attr_destroy(&attr);
    if(!CheckAndPrintErrorOnNonzero("attr_destroy", error))
        return 0;

    error = pthread_getattr_np(thread, &attr);
    if(!CheckAndPrintErrorOnNonzero("getattr", error))
        return 0;

    size_t stackSize;
    error = pthread_attr_getstacksize(&attr, &stackSize);
    if(!CheckAndPrintErrorOnNonzero("attr_getstacksize", error))
        return 0;

    cout << "Actual stack size: " << stackSize << '\n';

    error = pthread_attr_destroy(&attr);
    if(!CheckAndPrintErrorOnNonzero("attr_destroy", error))
        return 0;

    return 0;
}

----------------------------------------------

ulimit -a returns stack size (kbytes, -s) 8192

This:

https://linux.die.net/man/3/pthread_create
> Under the NPTL threading implementation, if the RLIMIT_STACK soft resource limit at the time the program started has any value other than "unlimited", then it determines the default stack size of new threads. Using pthread_attr_setstacksize(3), the stack size attribute can be explicitly set in the attr argument used to create a thread, in order to obtain a stack size other than the default.

Seems to suggest that the configured value is intended to be the default stack
size and not the max, I could be missing something.

----------------------------------------------

Observed behavior:

Output when ThreadStart() above is an empty function (return nullptr):
Actual stack size: 16777216

Output when ThreadStart() is as above:
<seg fault>

Even with a hard limit ulimit -Hs 8192 reports the same.

----------------------------------------------

Expected behavior:

If the ulimit configured stack size value is treated as the default stack size
and pthread_create is able to reserve more stack space than configured:
  - pthread_create succeeds and test case does not seg fault (requested stack
size is actually reserved)
  - OR pthread_create fails with EAGAIN

If the ulimit configured stack size value is treated as the max stack size and
pthread_create is not able to reserve more stack space than confiugred (this
appears to be the case):
  - pthread_create fails with EAGAIN

----------------------------------------------

In summary, if pthread_create is not able to reserve the requested stack size
then it is expected that it fails with EAGAIN, and that is not observed on
linux-arm64, and is observed on linux-x64.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the Glibc-bugs mailing list