This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: ctermid: return string literal, document MT-Safety pitfall
- From: Torvald Riegel <triegel at redhat dot com>
- To: Alexandre Oliva <aoliva at redhat dot com>
- Cc: Florian Weimer <fweimer at redhat dot com>, libc-alpha at sourceware dot org
- Date: Mon, 17 Nov 2014 11:05:34 +0100
- Subject: Re: ctermid: return string literal, document MT-Safety pitfall
- Authentication-results: sourceware.org; auth=none
- References: <ortx2b8l2k dot fsf at free dot home> <54620F80 dot 3030001 at redhat dot com> <ortx22ak52 dot fsf at free dot home> <5465EF19 dot 5040802 at redhat dot com> <or8ujdivcu dot fsf at free dot home> <54667764 dot 3060605 at redhat dot com> <oroas9gwqt dot fsf at free dot home>
On Fri, 2014-11-14 at 21:58 -0200, Alexandre Oliva wrote:
> On Nov 14, 2014, Florian Weimer <fweimer@redhat.com> wrote:
>
> > On 11/14/2014 05:45 PM, Alexandre Oliva wrote:
> >> Say, given:
> >>
> >> char foo[5] = "12";
> >>
> >> int main() {
> >> signal (SIGUSR1, checkme)
> >> strcpy (&foo[1], "23");
> >> }
> >>
> >> what standard-compliant values can checkme legitimately expect to find
> >> in foo[0], foo[1], foo[2], foo[3], and foo[4]?
>
> > foo is not an atomic object, so this is undefined.
>
> Yeah, I goofed in the testcase, and I failed to mention the reasoning
> was supposed to apply to earlier C standards, that we still intend to
> comply with, so our implementation of strcpy shouldn't gratuitously
> break.
>
> In order to avoid the undefinedness under e.g. C90, the actual string
> couldn't be in static storage. Getting ahold of a pointer to the string
> storage could be messy, though; maybe C90 and C99 were written so as to
> imply it couldn't be done at all, even if POSIX introduced means that
> would make it possible, such as writing the pointer to a pipe, or to a
> file using POSIX functions not defined in standard C. If their intent
> was to make access impossible, then my argument would indeed fall apart.
>
> > As a tried to explain, things turn out rather messy if you add the
> > _Atomic qualifier. I still think the values are unspecified (despite
> > the standard saying they are not) because the accesses from strcpy and
> > the signal handler are not sequenced.
>
> Once we make C11 the focus, getting the pointer to the signal handler is
> easier, through an _Atomic intptr_t with static or per-thread storage,
> but the string storage would have to be _Atomic as well, and then, as
> you say, what might happen within strcpy, memcpy et al is not entirely
> clear. However, making it unspecified might be pushing it too far.
For example, strcpy doesn't take atomic types as arguments, so it won't
access the memory atomically, so you get data races and undefined
behavior unless you make sure that the signal handler happens after or
before the strcpy (via happens-before).
Please have a look at C11 (N1570) 5.1.2.3p10, which gives an example of
an allowed implementation that just guarantees equality of non-volatiles
to the abstract machine at function boundaries.
> The standard could specify, for example, that it is unspecified, within
> an interrupting signal handler, whether observed values would be those
> originally held in the atomic storage, or those that should be put in
> there by the copy, without permitting any other values.
If the signal handler's atomic accesses are concurrent with other atomic
accesses, then there is no data race because atomics don't create data
races. But strcpy doesn't write with atomics.