On 2/2/2017 12:04 PM, Nick Kew wrote:
On Wed, 2017-02-01 at 00:23 +0100, Stefan wrote:
Hi,
the issue was discovered as part of tracing down a deadlock condition in
an SVN test [1].
As far as I understand it, the problem lies in the C-standard not
explicitly defining when a function registered with atexit() is called
in the context of thread termination [2].
I had no idea atexit() was called on thread termination. I guess the
manpage must be misleading in telling us it happens at process exit?
I expressed myself poorly a bit here. I didn't want to suggest
atexit()-registered functions are called on thread termination but
rather that threads can be terminated before the atexit-registered
functions are called.
So if apr_terminate is registered in a function called from a DLL via
atexit(), it can happen (and in my scenario does happen) that threads
got terminated before apr_terminate() is called.
Here's the code from the referenced repro-project mentioned in the
initial mail:
TESTDLL_API int fntestdll(void)
{
atexit(apr_terminate);
apr_initialize();
apr_pool_t *pool;
apr_pool_create_ex(&pool, NULL, NULL, NULL);
apr_thread_pool_t *thread_pool;
apr_thread_pool_create(&thread_pool, 0, 16, pool);
apr_thread_pool_idle_wait_set(thread_pool, 1000 * 1000);
for (int i = 0; i < 3; ++i) {
apr_thread_pool_push(thread_pool, foo, nullptr, 0, NULL);
}
return 0;
}
fntestdll is then called from the main-function in the test-application.
In this case it appears that the threads terminate first, before
apr_terminate() is executed.
I'm not sure whether this behavior is Windows-specific or not, but from
what I read/learned on the topic so far on the web, it seems that it's
outside the scope of the standard to say anything about DLLs and shared
library handling in this context.
While this particular issue could be prevented in other ways (including
platform specific solutions), I still think that the actual issue of the
current implementation is that trimming idle-threads does not handle
already detached/interrupted/terminated threads (while apr_join_thread's
return value actually indicates that to the caller. Hence the most
reasonable solution to this problem seemed to be the proposed patch.
--
Regards,
Stefan Hett