apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Branko ─îibej <br...@apache.org>
Subject Re: thread safety of apr_initialize
Date Sun, 22 Sep 2013 03:59:22 GMT
On 22.09.2013 04:06, Ken Been wrote:
> I am considering using a library (serf) built on APR in my own
> library.  Since I'm writing a library, I can make no assumptions about
> what the calling program does - it might have multiple threads started
> before it calls my library, and some of those threads might be using APR.
>
> My library can call apr_initialize, but I can't guarantee that it
> won't conflict with another call to apr_initialize in some other
> thread that I don't control.  Since apr_initialize doesn't seem to be
> thread safe, and I don't want to put (what I consider to be) onerous
> requirements on the users of my library, this effectively makes APR
> unusable for me.

If the application that uses your library also uses APR directly, it's
already responsible for initializing it in a single-threaded context. If
it doesn't, it's reasonable to require the app to call your library's
init function, which you can easily protect with a spinlock (that you
can implement using APR's atomic functions).

> So first, is my analysis correct?

Correct as far as it goes, but incomplete.

>   And second, if it is, is there some good reason that apr_initialize
> has not been made thread safe?  At first glance I think simply making
> "initialized++" an atomic operation should do it,

No, that wouldn't be enough. Just making the counter increment in
apr_initialize (and the decrement in apr_terminate) atomic will not
prevent race conditions. If two threads call apr_initialize
simultaneously, one of them could return with the assumption that APR
was initialized, while the second is still running the initialization
code. Hence the requirement that apr_initialize must be called in a
single-threaded context.

That said, it would still make sense to make the counter itself atomic,
if only to avoid unexpected results on architectures that do not
guarantee atomic reads and writes to word-sized memory locations.

> or if not then making the whole function body a critical section.  I'd
> be happy to work on a patch, but the fact that this hasn't been done
> makes me suspect there must be a good reason for that.

APR doesn't make assumptions about how an application uses it. So it's
up to the caller to make sure the initialization happens in a
single-threaded context.

That said ... the single-threaded initialization requirement isn't as
onerous as all that; it only requires the application to add two lines
of code in its main function (ignoring error handling):

    apr_initialize();
    atexit(apr_terminate());

Any non-trivial application will already have a ton of single-threaded
initialization code anyway, so the above will hardly make any difference.

If you don't want to expose the dependency on APR from your library, you
can create your own init function that the application would call
instead, and do the error handling and atexit(...) call from that.

-- Brane


Mime
View raw message