ports/105794: devel/ace: can not create more than ncpu threads with default thread flags

Andriy Gapon avg at icyb.net.ua
Thu Nov 23 16:50:22 UTC 2006


>Number:         105794
>Category:       ports
>Synopsis:       devel/ace: can not create more than ncpu threads with default thread flags
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 23 16:50:16 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Andriy Gapon
>Release:        FreeBSD 6.1-RELEASE-p2 i386
>Organization:
>Environment:
System:
FreeBSD 6.1-RELEASE-p2 i386
ace-5.5.1
libpthread is used as threads lib

>Description:
Please see the attached program.
It fails with the following output:
spawning thread #0
spawned thread #0 (thr_id=8053400)
spawning thread #1
spawn failure: Resource temporarily unavailable
Exit 71

ktrace shows the following information:
 27360 thread   GIO   fd 2 wrote 19 bytes
       "spawning thread #1
       "
 27360 thread   RET   write 19/0x13
 27360 thread   CALL  kse_create(0x804bf0c,0)
 27360 thread   RET   kse_create -1 errno 67 Too many processes

It seems that the problem occurs because flag THR_NEW_LWP, included into default set of ACE thread flags,
is interpreted by ACE library as an instruction to call pthread_setconcurrency with concurrency level
set to current number of threads created through ACE. FreeBSD libpthread refuses to set
concurrency higher than a number of CPUs available. ACE library treats pthread_setconcurrency() failure
as a fatal failure for thread creation.

Any solution for this problem should probably be submitted to ACE maintainers for
inclusion into ACE platform-specific source base.

>How-To-Repeat:
1. Change the attached program so that thr_num variable is greater than the number of CPUs on your test machine.
2. Compile the attached program:
$ c++ thread.cpp -o thread -I /usr/local/include -L /usr/local/lib -lACE -pthread
3. Make sure that libpthread is used as your thread support library:
$ ldd thread
thread:
        libACE.so.5 => /usr/local/lib/libACE.so.5 (0x48077000)
        libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x48196000)
        libm.so.4 => /lib/libm.so.4 (0x4826c000)
        libpthread.so.2 => /usr/lib/libpthread.so.2 (0x48283000)
        libc.so.6 => /lib/libc.so.6 (0x482aa000)

4. run the program

>Fix:

Workaround: use libthr as a threading library

Solution 1: change a meaning of THR_NEW_LWP on FreeBSD as term "LWP" is not directly
applicable to FreeBSD threading model. Reasonable approach is to alias THR_NEW_LWP
to THR_SCOPE_SYSTEM.

Solutuion 2: do not treat failure of pthread_setconcurrency() as a fatal error
for thread creation.

No patches, sorry.

--- thread.cpp begins here ---

#include <sysexits.h>

#include <ace/Log_Msg.h>
#include <ace/Thread.h>
#include <ace/Thread_Manager.h>

ACE_THR_FUNC_RETURN thr_func(void*)
{
	ACE_DEBUG((LM_DEBUG, ACE_TEXT("in thr_func\n")));
	ACE_OS::sleep(1);
	ACE_DEBUG((LM_DEBUG, ACE_TEXT("out thr_func\n")));
	return 0;
}

int ACE_TMAIN(int /*argc*/, ACE_TCHAR* /*argv*/[])
{
	ACE_TRACE(ACE_TEXT("main\n"));

	const int thr_num = 2;
	ACE_thread_t t_id[thr_num];

	for (int i = 0; i < thr_num; ++i) {
		ACE_DEBUG((LM_DEBUG, ACE_TEXT("spawning thread #%d\n"), i));
		if (ACE_Thread::spawn(thr_func, 0, THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, &t_id[i]) == -1) {
			ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("spawn failure: %m\n")), EX_OSERR);
		}
		ACE_DEBUG((LM_DEBUG, ACE_TEXT("spawned thread #%d (thr_id=%X)\n"), i, reinterpret_cast<unsigned long>(t_id[i])));
	}

	for (int i = 0; i < thr_num; ++i) {
		ACE_DEBUG((LM_DEBUG, ACE_TEXT("joining thread #%d\n"), i));
		ACE_Thread::join(t_id[i], 0, 0);
		ACE_DEBUG((LM_DEBUG, ACE_TEXT("joined thread #%d\n"), i));
	}

	return 0;
}
--- thread.cpp ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list