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

Reply via email to