Bug 386

Summary: pthread_create returns ENOMEM but should return EAGAIN
Product: glibc Reporter: Sebastien Decugis <sebastien.decugis>
Component: nptlAssignee: Ulrich Drepper <drepper.fsp>
Status: RESOLVED FIXED    
Severity: minor CC: glibc-bugs, jhaberman
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: test case
patch to fix the issue

Description Sebastien Decugis 2004-09-15 16:33:38 UTC
The POSIX standard explicitly requires the function to return EAGAIN if the
system lacks a resource to create the new thread. But when the function lacks
memory, the returned error code is ENOMEM.
Comment 1 Ulrich Drepper 2004-09-26 12:13:16 UTC
I don't think there is any case left where ENOMEM is returned.  If yes, provide
a test case.
Comment 2 Matthew Montgomery 2007-03-29 21:11:08 UTC
Hello, 

If you set ulimit -s 512000 (thread_stack) on a 32bit system with >2GB RAM it is
possible to get pthread_create to return ENOMEM.  Strangely, ulimit -s unlimited
or ulimit -s 8192 does not produce this ENOMEM result.

Does pthread_create allocate a whole thread_stack size buffer for each thread if
a ulimit -s is defined?

See: http://bugs.mysql.com/bug.php?id=27487
OS error code  12:  Cannot allocate memory

InnoDB: Error: pthread_create returned 12
070329 14:54:41  mysqld ended

This behavior has been experienced on:

RHEL3 (2.4.21-37.ELsmp) 
and
SuSE 10.1 (2.6.16.13-4-default)
glibc-2.4-31

Comment 3 Anton Ghiugan 2007-06-13 20:37:42 UTC
Oddly enough, it is more convenient to return the actual error code rather than 
generic EAGAIN  (which would leave programmers blind ...). I would rather say 
to revise POSIX standard.... 
Comment 4 Ulrich Drepper 2007-10-07 22:13:37 UTC
You haven't shown where in the current libc code there is a problem.  Citing
ancient libcs has no value at all.  Here we are concern exclusively with
current, upstream code.
Comment 5 Halesh S 2008-07-03 13:52:02 UTC
Hi,

Even pthread_create() returns the errno, but it doestnot sets the errno EAGAIN, 
instead it retains the ENOMEM. I have verified in glibc-2.7.

Thats why the attached testcase results in..

$gcc -o test test.c -lpthread

$./test
pthread_create : Cannot allocate memory -> 12
Created 405 threads
pthread_create : Cannot allocate memory -> 12
..........
..........

errno value set to 12 (ENOMEM)
but needs to be EAGAIN.


Ths attached patch fixes this issue.

$./test
pthread_create : Resource temporarily unavailable -> 11
Created 405 threads
pthread_create : Resource temporarily unavailable -> 11
................
................

Thanks,
Halesh





Comment 6 Halesh S 2008-07-03 13:53:21 UTC
Created attachment 2813 [details]
test case

Test Case
Comment 7 Halesh S 2008-07-03 13:53:58 UTC
Created attachment 2814 [details]
patch to fix the issue
Comment 8 Ulrich Drepper 2008-07-26 23:51:45 UTC
Don't ever report problem unless you can reproduce them with the latest glibc
code from cvs.  I've said this before, even in this bug, why the f*ck don't you
read that first?  There is no problem I can see in the current code.
Comment 9 Josh Haberman 2011-05-10 00:27:37 UTC
I was just able to reproduce this.  Using strace I discovered that ENOMEM was coming from the mprotect() call that sets up the guard page.  And indeed this seems to be a case that isn't converting ENOMEM -> EAGAIN.

http://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/allocatestack.c;h=ba251b91626cd1463a19f9db3fbed85eec585897;hb=be9c5e8b2014bdbf724f206bb25249c67115db49#l636

mprotect() returns ENOMEM if you've hit the maximum number of mappings for a process (which on Linux is currently is 65050).
Comment 10 Ulrich Drepper 2011-05-11 22:24:22 UTC
(In reply to comment #9)
> I was just able to reproduce this.  Using strace I discovered that ENOMEM was
> coming from the mprotect() call that sets up the guard page.  And indeed this
> seems to be a case that isn't converting ENOMEM -> EAGAIN.

That's a good catch.  I changed the code.
Comment 11 Jackie Rosen 2014-02-16 19:38:56 UTC Comment hidden (spam)