public inbox for libc-help@sourceware.org
 help / color / mirror / Atom feed
* raise() marked __leaf__ is not C-compliant?
@ 2020-10-27 16:57 Tadeus Prastowo
  2020-10-27 18:50 ` Adhemerval Zanella
  2020-10-28  8:21 ` Florian Weimer
  0 siblings, 2 replies; 14+ messages in thread
From: Tadeus Prastowo @ 2020-10-27 16:57 UTC (permalink / raw)
  To: libc-help

[-- 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;
}

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

end of thread, other threads:[~2020-10-29  7:50 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-27 16:57 raise() marked __leaf__ is not C-compliant? Tadeus Prastowo
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

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).