Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is stack size of Linux process related to pthread, fork and exec

I have a question about the stack size of a process on Linux. Is this stack size determined at linkage time and is coded in the ELF file?

I wrote a program which prints its stack size by

pthread_attr_getstacksize(&attr, &stacksize);

And if I run this program directly from a shell, it gives a value of about 10MB. But when I exec it from a thread which belongs to a multi-thread program, it gives a value of about 2MB.

So I want to know what factors affect the stack size of a process which is fork and exec-ed from some parent process. And is it possible to set the stack size of a process in its parent at run time before fork and exec the child?

like image 927
Feng Avatar asked Feb 26 '10 07:02

Feng


People also ask

What is Pthread stack size?

From the pthread_create() description: On Linux/x86-32, the default stack size for a new thread is 2 megabytes.

What is stack size Linux?

The default Linux stack size per thread is 10MB, where as, on Windows the default is 1MB. This causes the server on Linux to allocate an excessive amount of unneeded memory due to the # of threads created by the server.

How is stack size defined?

The stack size is determined when the thread is created since it needs to occupy contiguous address space. That means that the entire address space for the thread's stack has to be reserved at the point of creating the thread. If the stack is too small then it can overflow.

Do pthreads use forks?

The pthread_atfork() function declares fork() handlers that are called before and after fork() in the context of the thread that called fork() . The prepare handler is called before fork() starts. The parent handler is called after fork() returns in the parent.


2 Answers

As the manpage for pthread_create(3) says:

"On Linux/x86-32, the default stack size for a new thread is 2 megabytes", Unless the RLIMIT_STACK resource limit (ulimit -s) is set: in that case, "it determines the default stack size of new threads".

You can check this fact by retrieving the current value of RLIMIT_STACK with getrlimit(2), as in the following program:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>

int main()
{
    /* Warning: error checking removed to keep the example small */
    pthread_attr_t attr;
    size_t stacksize;
    struct rlimit rlim;

    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr, &stacksize);
    getrlimit(RLIMIT_STACK, &rlim);
    /* Don't know the exact type of rlim_t, but surely it will
       fit into a size_t variable. */
    printf("%zd\n", (size_t) rlim.rlim_cur);
    printf("%zd\n", stacksize);
    pthread_attr_destroy(&attr);

    return 0;
}

These are the results when trying to run it (compiled to a.out) from the command line:

$ ulimit -s
8192
$ ./a.out 
8388608
8388608
$ ulimit -s unlimited
$ ./a.out 
-1
2097152
$ ulimit -s 4096
$ ./a.out 
4194304
4194304
like image 152
Danilo Piazzalunga Avatar answered Oct 07 '22 20:10

Danilo Piazzalunga


According to the man page for fork(), "The child process is created with a single thread—the one that called fork()."

So, the stack size of the main thread for the child process will be the stack size of the thread that calls fork().

But, when one of the exec() functions is called (ultimately calling execve() to do the real work), the process image is replaced with the new program. At that time, the stack is re-created according to the stack size soft limit (kernel 2.6.23 and later), which can be seen by calling getrlimit(RLIMIT_STACK, &rlimitStruct).

You can control this before calling exec by setting the soft limit using setrlimit(RLIMIT_STACK, &rlimitStruct) (provided you don't try to increase the hard limit or set the soft limit higher than the hard limit).

like image 41
jtchitty Avatar answered Oct 07 '22 21:10

jtchitty