public inbox for libc-help@sourceware.org
 help / color / mirror / Atom feed
From: Tadeus Prastowo <0x66726565@gmail.com>
To: libc-help@sourceware.org
Subject: raise() marked __leaf__ is not C-compliant?
Date: Tue, 27 Oct 2020 17:57:47 +0100	[thread overview]
Message-ID: <CAA1YtmtVEcvOOyo+crpNg=p382hyQv47=K3sv1oPgk-AKnN=QA@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2411 bytes --]

Hello,

To quote C18 on the signal() function
(https://web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf),
Section 7.14.1.1 Paragraph 5:

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.

My understanding is that if my single-threaded program installs a
signal handler using signal() and the handler is executed as a result
of calling raise(), then the handler has a defined behavior when the
handler accesses any object with static storage duration even though
the object is not qualified using volatile and not of type
sig_atomic_t.

If my understanding is incorrect, I would like to have some pointer to
parts of the C standard that say so.

Otherwise, why glibc 2.30 implements raise() on x86_64 by using the
GCC function attribute __leaf__ when GCC says
(https://gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes):

Note that leaf functions might indirectly run a signal handler defined
in the current compilation unit that uses static variables. Similarly,
when lazy symbol resolution is in effect, leaf functions might invoke
indirect functions whose resolver function or implementation function
is defined in the current compilation unit and uses static variables.
There is no standard-compliant way to write such a signal handler,
resolver function, or implementation function, and the best that you
can do is to remove the leaf attribute or mark all such static
variables volatile.

End quote.

I see the use of the __leaf__ attribute by glibc 2.30 by reading
/usr/include/signal.h, finding __THROW, and then reading
/usr/include/sys/cdefs.h for __THROW definition, which expands to
include the __leaf__ attribute.

With glibc-2.30 raise() being marked __leaf__, the attached C program
has an undefined behavior because it terminates when compiled with GCC
using either -O0 or -Os but enters an infinite loop when using -O2.

Should glibc 2.30 be compiled in a specific way to have the defined
behavior guaranteed by the C standard?  If yes, what configure options
should be used?

Thank you.

-- 
Best regards,
Tadeus

[-- Attachment #2: raise.c --]
[-- Type: text/x-csrc, Size: 1069 bytes --]

/* Compile this as follows:
 *   gcc -O0 -o raise raise.c
 * The C standard on signal() guarantees that the execution of raise will
 * terminate.
 *
 * Compile this as follows:
 *   gcc -Os -o raise raise.c
 * The C standard on signal() guarantees that the execution of raise will
 * terminate.
 *
 * Compile this as follows:
 *   gcc -O2 -o raise raise.c
 * The C standard on signal() guarantees that the execution of raise will
 * terminate.  Unfortunately, glibc-2.30 raise() is marked __leaf__, and so, the
 * execution won't terminate on a x86_64 machine.
 */

#include <signal.h>
#include <stdlib.h>
#include <time.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 one */

  signal(SIGUSR1, handler);

  /* This is an infinite loop unless terminated is 1 as delta is surely 0 */
  for (int i = 0; !terminated && i < 100; i += delta) {
    total += i;
    raise(SIGUSR1);
  }
  
  return total;
}

             reply	other threads:[~2020-10-27 16:57 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-27 16:57 Tadeus Prastowo [this message]
2020-10-27 18:50 ` Adhemerval Zanella
2020-10-28  5:47   ` Tadeus Prastowo
2020-10-28  6:13     ` Tadeus Prastowo
2020-10-28  7:33       ` Tadeus Prastowo
2020-10-28 11:53         ` Adhemerval Zanella
2020-10-28 13:19           ` Tadeus Prastowo
2020-10-28 17:34             ` Adhemerval Zanella
2020-10-28 19:23               ` Tadeus Prastowo
2020-10-28 20:17                 ` Adhemerval Zanella
2020-10-29  7:50                   ` Tadeus Prastowo
2020-10-28  8:21 ` Florian Weimer
2020-10-28 12:58   ` Tadeus Prastowo
2020-10-28 17:16     ` Tadeus Prastowo

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='CAA1YtmtVEcvOOyo+crpNg=p382hyQv47=K3sv1oPgk-AKnN=QA@mail.gmail.com' \
    --to=0x66726565@gmail.com \
    --cc=libc-help@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).