bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: new module for temporary files in temporary directories


From: Paul Eggert
Subject: Re: new module for temporary files in temporary directories
Date: Thu, 06 Jul 2006 00:41:29 -0700
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Ben Pfaff <address@hidden> writes:

> The issue at hand, as I understand it, is not even the general
> behavior of signals.  It is the behavior of fatal signals.  That
> is, a the program terminates without ever returning from the
> signal handler.  This is much simpler than the general problem

Yes, good point; it is simpler.  However, my impression is that the
new module's cleanup function is intended to be callable even from
non-fatal signal handlers, so I don't think we have the simpler case
here.  But for now let's concentrate on the simpler case.

> However, I believe that if the assignment in main were changed to
> the following, then the signal handler would be guaranteed to see
> 1 in x if the signal arrived in getchar;
>         *(sig_atomic_t volatile *) &x = 1;

OK, so it sounds like your idea is that, if all accesses to an object
are via a volatile lvalue, then the object is volatile, even if it was
not originally defined to be a volatile object.  This idea has an
intuitive appeal, though I submit that it does not follow from the
standard; the standard does not explicitly specify or even suggest
this "all accesses" rule.

A problem I see with this idea is 6.7.3.(6), which says "An object
that has volatile-qualified type may be modified in ways unknown to
the implementation or have other unknown side effects."  So a volatile
object (I assume this is the same as "an object that has
volatile-qualified type" in your model?) can spontaneously change, for
reasons unknown to and outside the control of the program; this point
is underlined later in the paragraph.  But if all accesses to a
humdrum "static int x;" object are via volatile lvalues, and if that
means "x" is a volatile object, doesn't this also mean "x" might
spontaneously change?

One way out of this mess would be to say that we are making an extra
assumption, not present in the standard, that volatile objects do not
spontaneously change and that they have no unknown side effects.  To
some extent we must make this assumption anyway, or we'll get nowhere.
Still, 6.7.3.(6) makes it clear (at least to me) that "volatile" is
intended more for describing access to memory-mapped device registers,
and wasn't really intended for use in safe signal handling or
multithreading.

There is also the huge escape clause at the end of 6.7.3.(6): "What
constitutes an access to an object that has volatile-qualified type is
implementation-defined."  Ouch!  Talk about getting run over by an
express train!

Anyway, to get back to the original module, it seems to me that the
code actually is assuming something quite a bit different from what
'volatile' provides.  The code is attempting to do use loads and
stores as barriers to prevent the usual sorts of bugs with signal
handling.  But 'volatile' is not designed to handle this problem:
volatile accesses are not guaranteed to be atomic.

There has been quite a bit of effort in the C++ community recently to
add support for atomic operations; see the cpp-threads mailing list
<http://www.decadentplace.org.uk/pipermail/cpp-threads/>.  The latest
proposal is H.-J. Boehm's WG21/N2047 J16/06-0117
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2047.html>
(2006-06-24).  It contains a C API, and indicates the sort of problems
that people run into with real hardware (albeit not limiting
themselves to signal-handler problems), but this stuff is still very
much in a state of flux.


> Perhaps all this is moot because Bruno's
> module does not actually contain any casts to volatile.

But the module contains casts to types like "struct tempdir * volatile *",
e.g.:

          struct tempdir * volatile *new_array =
            (struct tempdir * volatile *)
            xmalloc (new_allocated * sizeof (struct tempdir * volatile));

and this raises the issue we've been talking about (what I've been
calling "volatile objects" versus "volatile lvalues").  And the point
wouldn't be moot even if the module had no casts, because you can
convert e.g., "void *" to "int volatile *" in C without a cast.  My
example in
<http://lists.gnu.org/archive/html/bug-gnulib/2006-07/msg00062.html>
relies on this sort of thing: it has no casts but does have the problem.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]