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?
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
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).