public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "0x66726565 at gmail dot com" <sourceware-bugzilla@sourceware.org>
To: glibc-bugs@sourceware.org
Subject: [Bug libc/26802] New: raise() marked __leaf__ is not C-compliant
Date: Wed, 28 Oct 2020 17:14:02 +0000	[thread overview]
Message-ID: <bug-26802-131@http.sourceware.org/bugzilla/> (raw)

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.

             reply	other threads:[~2020-10-28 17:14 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-28 17:14 0x66726565 at gmail dot com [this message]
2020-10-28 19:57 ` [Bug libc/26802] " 0x66726565 at gmail dot com
2022-07-25 21:25 ` amonakov at gmail dot com

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-26802-131@http.sourceware.org/bugzilla/ \
    --to=sourceware-bugzilla@sourceware.org \
    --cc=glibc-bugs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).