This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Async-signal-safe access to __thread variables from dlopen()ed libraries?
- From: Rich Felker <dalias at aerifal dot cx>
- To: Torvald Riegel <triegel at redhat dot com>
- Cc: Carlos O'Donell <carlos at redhat dot com>, Ian Lance Taylor <iant at google dot com>, Paul Pluzhnikov <ppluzhnikov at google dot com>, Roland McGrath <roland at hack dot frob dot com>, Richard Henderson <rth at twiddle dot net>, GNU C Library <libc-alpha at sourceware dot org>, Andrew Hunter <ahh at google dot com>, Alexandre Oliva <aoliva at redhat dot com>
- Date: Mon, 7 Oct 2013 18:53:42 -0400
- Subject: Re: Async-signal-safe access to __thread variables from dlopen()ed libraries?
- Authentication-results: sourceware.org; auth=none
- References: <20131002205046 dot GT20515 at brightrain dot aerifal dot cx> <1381010778 dot 8757 dot 3460 dot camel at triegel dot csb> <20131006053800 dot GQ20515 at brightrain dot aerifal dot cx> <1381095401 dot 8757 dot 3814 dot camel at triegel dot csb> <20131006214057 dot GA14037 at brightrain dot aerifal dot cx> <1381096560 dot 8757 dot 3846 dot camel at triegel dot csb> <20131007141425 dot GU20515 at brightrain dot aerifal dot cx> <1381168100 dot 8757 dot 4498 dot camel at triegel dot csb> <20131007181620 dot GE20515 at brightrain dot aerifal dot cx> <1381182637 dot 18547 dot 133 dot camel at triegel dot csb>
On Tue, Oct 08, 2013 at 12:50:37AM +0300, Torvald Riegel wrote:
> I don't think it matters whether we're dealing with a char type or, say,
> an int; both don't require the compiler to ensure that observations by
> signal handlers return meaningful values. Let's look at an example:
>
> char foo = 1;
>
> void handler() { x = foo; } // Can it read 42?
>
> foo = 2;
> *p = 0; // This causes a signal to be handled.
> foo = 3;
>
> Can the handler read a value of 42 for foo? I think this is allowed
> behavior because the compiler can assume that the accesses to foo are
> sequential; thus, it could for example reuse the variable's memory
> location for other stuff (eg, it's stack slot). The handler could
> probably also read 1, because the compiler could just remove the (dead)
> store of 2.
>
> Why do you think that optimizations like those mentioned above would be
> disallowed for char types?
I don't. It's not disallowed for sig_atomic_t either. The magic
ingredient that disallows these optimizations is volatile. But you
can't just use volatile with any type to communicate between signal
handlers and the main flow of execution; you have to use sig_atomic_t
too. Why? As I see it, there are two reasons:
1. In general, objects could be written as multiple parts (for
example, on x86_64, 64-bit values are sometimes written as two
32-bit slots). Note that this could never apply to char unless you
had a pathological architecture with only single-bit writes or
similar.
2. Conversely, prior to C11 (and only on non-POSIX implementations)
objects could be written as a read-modify-write cycle on a larger
unit of memory. This could have applied to char types in the past,
but it's no longer permitted. (As you noted before, it could still
be implemented under the hood with a read-modify-CAS loop, but
since this is not observably different from writing the
correct-sized object, it doesn't matter.)
My view is that, since reason 1 never applies to char types (modulo
the pathological/hypothetical bit-based arch) and reason 2 can no
longer apply anywhere, "volatile char" should be just as valid to
access from signal handlers as "volatile sig_atomic_t" is.
By the way, if you haven't already, please see my related open issue
on the Austin Group tracker:
http://austingroupbugs.net/view.php?id=728
I don't claim it's entirely (or even nearly) correct at this point,
but it's a starting point for fixing some of these things.
Rich