From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <0x66726565@gmail.com> Received: from mail-il1-x12d.google.com (mail-il1-x12d.google.com [IPv6:2607:f8b0:4864:20::12d]) by sourceware.org (Postfix) with ESMTPS id 5BAA33857039 for ; Wed, 28 Oct 2020 07:33:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5BAA33857039 Received: by mail-il1-x12d.google.com with SMTP id y17so3833523ilg.4 for ; Wed, 28 Oct 2020 00:33:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=sdu7n4uh/dmb/xSCeZhfAPsgJJifcfTwvqucbotY40E=; b=qW7kCk/lSj+29OxnDy7d6I0oTfK0UjmF2J05bu7639RJegP2A/N2oDg7tGp0Jwer25 4FswPi//i4dsN2vl6zW98M/U75pAYQs18lvjF22c3a2r1kKLM8KtUTPp0FpFZB7UMNQD 5uWhb810oozJc+FC9S4LdCLvTktZHkV/3UqQSemzUpfx4A5ADDW6xpuU8CgUWh5CeUQL woVjKdxJqZoLJGR1SkmNwRwAacqOJ+pQ0eIZGotpDyD0++2QqClPiLEtlDl64P9jSH8M 4Xot37T+lRSicOsH7eoW3Uj5FHBAXJtx9XVejvEhsKjC9rkgnP2oxAcdKMaG42Pp0QeJ IRbw== X-Gm-Message-State: AOAM533EHH5rE7Ik+UMj0ufxDr5QJ3mrWOd6nzQG508pExYJ6TO4x2vW 7A5OVx0UkfFLx0rMxt+d0vWwhsi4I9h5UaqkxA== X-Google-Smtp-Source: ABdhPJyPgnCLVvggPCnY4wyggWqm9Lv27c/S+5ckhPDHEqxFhjlFS+/MStx+DbyTbqh/gtQOreLcAuzUW6+1mZWlplQ= X-Received: by 2002:a92:c213:: with SMTP id j19mr4896217ilo.205.1603870430605; Wed, 28 Oct 2020 00:33:50 -0700 (PDT) MIME-Version: 1.0 References: <25b5791b-5368-7a78-f80d-5ceb2b618d72@linaro.org> In-Reply-To: From: Tadeus Prastowo <0x66726565@gmail.com> Date: Wed, 28 Oct 2020 08:33:39 +0100 Message-ID: Subject: Re: raise() marked __leaf__ is not C-compliant? To: Adhemerval Zanella Cc: "libc-help@sourceware.org" Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URI_DOTEDU autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-help@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-help mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Oct 2020 07:33:53 -0000 Allow me to fix some mistakes in my previous e-mails: On Wed, Oct 28, 2020 at 7:13 AM Tadeus Prastowo <0x66726565@gmail.com> wrote: > > Sorry that I closed this thread too soon and reopen it again now after > re-reading GCC documentation because the GCC documentation thinks that > raise() should not be marked __leaf__. > > On Wed, Oct 28, 2020 at 6:47 AM Tadeus Prastowo <0x66726565@gmail.com> wrote: > > > > On Tue, Oct 27, 2020 at 7:50 PM Adhemerval Zanella > > wrote: > > > > > > On 27/10/2020 13:57, Tadeus Prastowo via Libc-help wrote: > > > > > > > > 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. > > > > > > Unfortunately this is not fully correct, specially if you accessing the > > > object outside the signal handler. As you have noticed in your example, > > > compiler can assume the variable 'terminated' won't be modified outside > > > the function and apply optimization that avoid read its value from > > > memory (most likely GCC will optimize out the '!terminated'). > > > > However, the compiler cannot assume that the variable `terminated' > > won't be modified outside the loop if the loop calls a function whose > > definition the compiler does not see (e.g., the raise() function > > defined by glibc). Otherwise, the compiler is wrong if the loop calls > > a function defined in another translation unit because the function > > may modify `terminated'. > > > > > One of the best didactic explanation I have for this is from [1]. > > > > > > [1] https://wiki.sei.cmu.edu/confluence/display/c/SIG31-C.+Do+not+access+shared+objects+in+signal+handlers > > > > Thank you for the reference. > > > > I have studied it but found no pointer to parts of the C standard that > > says that it is an undefined behavior to call a signal handler > > synchronously using raise() on a normal execution path (i.e., not from > > within another signal handler, which certainly is undefined behavior > > as noted in "undefined behavior 131"). I meant to say: I have studied it but found no pointer to parts of the C standard that says that it is an undefined behavior to access a non-volatile object with static storage duration from within a signal handler that is called synchronously using raise() on a normal execution path (i.e., the note "undefined behavior 131" only talks about an undefined behavior that results from calling raise() from within a signal handler). > > I know that the safest thing to do is always to qualify such a > > variable with `volatile', but I think it is valid to not do so for the > > cases that are not stated as > > undefined/unspecified/implementation-defined behavior by the C > > standard. > > That is why I ask for a pointer to parts of the C standard > > if indeed calling a signal handler synchronously using raise() on a > > normal execution path is an undefined behavior. I meant to say: That is why I ask for a pointer to parts of the C standard if indeed accessing a non-volatile object with static storage duration from within a signal handler that is called synchronously using raise() on a normal execution path is an undefined behavior. > > After further thought, I found out that the problem is not glibc-2.30 > > marking raise() with __leaf__ but the file-scope limitation of > > `terminated'. As I already mentioned, since `terminated' has a > > file-scope, the compiler can assume that `terminated' will not be > > modified by a function defined in another translation unit. And > > hence, the compiler is correct in optimizing out the `!terminated'. > > Once `terminated' has a global scope, the compiler correctly does not > > optimize it out as exemplified by the attached program. So, marking > > raise() with __leaf__ does not make raise() non-compliant with the C > > standard. > > After re-reading the GCC documentation, I think marking raise() with > __leaf__ makes raise() non-compliant with the C standard, unless the C > standard says that calling a signal handler synchronously using > raise() on a normal execution path is an undefined behavior. I meant to say: After re-reading the GCC documentation, I think marking raise() with __leaf__ makes raise() non-compliant with the C standard, unless the C standard says that accessing a non-volatile object with static storage duration from within a signal handler that is called synchronously using raise() on a normal execution path is an undefined behavior. > The GCC documentation on __leaf__ > (https://gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes) > says (words in square brackets are added to fit our 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. > > Glibc-2.30 raise() definitely runs a signal handler, and the signal > handler can be defined in the current compilation unit using static > variables. So, unless the C standard says that calling a signal > handler synchronously using raise() on a normal execution path is an > undefined behavior, the marking of raise() with __leaf__ makes raise() > non-compliant with the C standard. I meant to say: Glibc-2.30 raise() definitely runs a signal handler, and the signal handler can be defined in the current compilation unit to use static variables. So, unless the C standard says that accessing a non-volatile object with static storage duration from within a signal handler that is called synchronously using raise() on a normal execution path is an undefined behavior, the marking of raise() with __leaf__ makes raise() non-compliant with the C standard. > May I know your opinion, please? Thank you for your patience. -- Best regards, Tadeus