public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libc/26802] New: raise() marked __leaf__ is not C-compliant
@ 2020-10-28 17:14 0x66726565 at gmail dot com
  2020-10-28 19:57 ` [Bug libc/26802] " 0x66726565 at gmail dot com
  2022-07-25 21:25 ` amonakov at gmail dot com
  0 siblings, 2 replies; 3+ messages in thread
From: 0x66726565 at gmail dot com @ 2020-10-28 17:14 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=26802

            Bug ID: 26802
           Summary: raise() marked __leaf__ is not C-compliant
           Product: glibc
           Version: 2.30
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: 0x66726565 at gmail dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---

To quote the C standard on the signal() function (C90, C99, C11, and C18
basically say the same) described in Section 7.14.1.1 Paragraph 5 of [1]:

If the signal occurs other than as the result of calling the abort or raise
function, the behavior is undefined if the signal handler refers to any object
with static or thread storage duration that is not a lock-free atomic object
other than by assigning a value to an object declared as volatile sig_atomic_t

End quote.

Based on that, a signal handler that is run as the result of calling raise()
has no UB (undefined behavior) when the handler accesses an object with static
storage duration that is not qualified with volatile.  Indeed, the C standard
does not say that it is a UB to access an object with static storage duration
that is not qualified with volatile and/or is not of type sig_atomic_t from a
signal handler that is run as the result of calling raise().

However, glibc 2.30 for my x86_64 machine managed by the Linux kernel version
4.15.0 marks raise() using the GCC function attribute __leaf__.  This results
in a UB because the following test program terminates when compiled by GCC with
-O0 and -Os but never terminates when compiled by GCC with -O2:

-- 8< --------------------
#include <signal.h>
#include <stdlib.h>

static int terminated;

static void handler(int signo)
{
  terminated = 1;
}

int main(int argc, char **argv) {
  unsigned total = 0, delta = drand48() >= argc ? 1 : 0;
  /* At runtime, delta will be 0 as argc is 1 */

  signal(SIGUSR1, handler);

  /* Infinite loop unless `terminated' is 1 (delta is 0) */
  for (int i = 0; !terminated && i < 100; i += delta) {
    total += i;
    raise(SIGUSR1); /* synchronously runs `handler' */
  }

  return total;
}
-- 8< --------------------

As a reminder, the C standard says the following about the raise() function
(C99, C11, and C18 basically say the same), which is stated on page 195 of [1]:

If a signal handler is called, the raise function shall not return until after
the signal handler does.

End quote.

Now the GCC documentation on __leaf__ [2] says the following (words in square
brackets are additions/replacements to fit this context):

Note that leaf functions might indirectly run a signal handler defined in the
current compilation unit that uses static variables.  [...] There is no
standard-compliant way to write such [an] implementation function[, for
example, glibc-2.30 raise()], and the best that you can do is to remove the
leaf attribute or mark all such static variables volatile.

End quote.

Since glibc-2.30 raise() definitely runs a signal handler as required by the C
standard, and the signal handler can be defined in the current compilation unit
to use static variables, then unless the C standard says that it is a UB to
access a non-volatile object with static storage duration from within a signal
handler that is run using raise() on a normal execution path, the marking of
raise() with __leaf__ makes raise() non-compliant with the C standard, and
hence, this bug report.

Therefore, this bug report requests that, to be compliant with the C standard,
glibc does not mark raise() with __leaf__.  Furthermore, if glibc aims to be
POSIX-compliant as well, in accordance with IEEE Std 1003.1-2017, Volume 2
"System Interfaces", Section 2.4.3 "Signal Actions", the following functions
should not be marked with __leaf__ as well: abort(), raise(), kill(),
pthread_kill(), and sigqueue().  Thank you for your attention.

References:
[1]
https://web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf
[2]
https://gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug libc/26802] raise() marked __leaf__ is not C-compliant
  2020-10-28 17:14 [Bug libc/26802] New: raise() marked __leaf__ is not C-compliant 0x66726565 at gmail dot com
@ 2020-10-28 19:57 ` 0x66726565 at gmail dot com
  2022-07-25 21:25 ` amonakov at gmail dot com
  1 sibling, 0 replies; 3+ messages in thread
From: 0x66726565 at gmail dot com @ 2020-10-28 19:57 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=26802

--- Comment #1 from Tadeus Prastowo <0x66726565 at gmail dot com> ---
This paragraph written in the bug description is inaccurate as detailed in [1]:
Since glibc-2.30 raise() definitely runs a signal handler as required by the C
standard, and the signal handler can be defined in the current compilation unit
to use static variables, then unless the C standard says that it is a UB to
access a non-volatile object with static storage duration from within a signal
handler that is run using raise() on a normal execution path, the marking of
raise() with __leaf__ makes raise() non-compliant with the C standard, and
hence, this bug report.

The correct one is as follows: Since glibc-2.30 raise() may run a signal
handler that is defined in the current compilation unit to use static
variables, then unless the C standard says that it is a UB to access a
non-volatile object with static storage duration from within a signal handler
that is run using raise() on a normal execution path, the marking of raise()
with __leaf__ makes raise() non-compliant with the C standard, and hence, this
bug report.

[1] https://sourceware.org/pipermail/libc-help/2020-October/005522.html

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug libc/26802] raise() marked __leaf__ is not C-compliant
  2020-10-28 17:14 [Bug libc/26802] New: raise() marked __leaf__ is not C-compliant 0x66726565 at gmail dot com
  2020-10-28 19:57 ` [Bug libc/26802] " 0x66726565 at gmail dot com
@ 2022-07-25 21:25 ` amonakov at gmail dot com
  1 sibling, 0 replies; 3+ messages in thread
From: amonakov at gmail dot com @ 2022-07-25 21:25 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=26802

Alexander Monakov <amonakov at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |amonakov at gmail dot com

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-07-25 21:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-28 17:14 [Bug libc/26802] New: raise() marked __leaf__ is not C-compliant 0x66726565 at gmail dot com
2020-10-28 19:57 ` [Bug libc/26802] " 0x66726565 at gmail dot com
2022-07-25 21:25 ` amonakov at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).