Hi,

Someone in the Subversion team made our C tests run in parallel. With that
our buildbot found a race condition in the Windows specific
APR_DECLARE_LATE_DLL_FUNC() implementation.

The current code is
[[
#define APR_DECLARE_LATE_DLL_FUNC(lib, rettype, calltype, fn, ord, args,
names) \
    typedef rettype (calltype *apr_winapi_fpt_##fn) args; \
    static apr_winapi_fpt_##fn apr_winapi_pfn_##fn = NULL; \
    static int apr_winapi_chk_##fn = 0; \
    static APR_INLINE int apr_winapi_ld_##fn(void) \
    {   if (apr_winapi_pfn_##fn) return 1; \
        if (apr_winapi_chk_##fn ++) return 0; \
        if (!apr_winapi_pfn_##fn) \
            apr_winapi_pfn_##fn = (apr_winapi_fpt_##fn) \
                                      apr_load_dll_func(lib, #fn, ord); \
        if (apr_winapi_pfn_##fn) return 1; else return 0; }; \
    static APR_INLINE rettype apr_winapi_##fn args \
    {   if (apr_winapi_ld_##fn()) \
            return (*(apr_winapi_pfn_##fn)) names; \
        else { SetLastError(ERROR_INVALID_FUNCTION); return 0;} }; \

#define APR_HAVE_LATE_DLL_FUNC(fn) apr_winapi_ld_##fn()
]]

(I can reproduce the problem locally)

The ++ on the second line of the function body makes calls in other threads
skip the initialization, which may cause them to see no function (or
theoretically a bad pointer).

I think the dll load function should be converted to a more stable pattern,
that properly handles multiple threads. And perhaps we should just assume a
few more NT functions to be alsways there instead of loading them
dynamically.

        Bert

Reply via email to