From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <0x66726565@gmail.com> Received: from mail-il1-x134.google.com (mail-il1-x134.google.com [IPv6:2607:f8b0:4864:20::134]) by sourceware.org (Postfix) with ESMTPS id 781523858005 for ; Wed, 28 Oct 2020 06:14:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 781523858005 Received: by mail-il1-x134.google.com with SMTP id z2so3666139ilh.11 for ; Tue, 27 Oct 2020 23:14:04 -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=65jG9pCSswMcmjRAEJBifQtaPfi2wENLMDCLVND7Zks=; b=G81Ss9iLAZ6ajsSg2rMcafXDUGKOh2jTD7Io+bK3WfrMnLv3u2hYOot6msUZEonbq0 0NwBSSVGmpDrmKaEVQRL/F2AoXU1ZWqy0xmCb3we6um7pUwLJmzC1rw8s3uBFIvskz6K sjeYrp3V0AmI+tqxDuyLPZY6ok7kxIcJQidY2QqmVZy1sQqkXeDlgYR7Av7kbMrhKsiz KyuYPxGDq7j7Hz1Pawd/DGx6tO1hmH0A19hLvu2H7hrMxwzVBsUaOQcIzqf9QK62IStc aUVlXusFkjz7Bd/HRJBRe5ID9p27f7luQTtPkZ12e2LRCDYiF3HT2KBjwhh8WbyAgMUR 9UYA== X-Gm-Message-State: AOAM530tSSje2PLVseoi0pjd/Eex28zmmvwp3pGozBGxznFBjIgV4rYQ 36U5pkPQqPHvoAgH75YhFxeqdKu58YE71ymPqg== X-Google-Smtp-Source: ABdhPJyEVcgURPxI7Jqjj6z8iEuXkcqb09E4klp6Ts/5YoMiLof6JPEwztyT4UkoKZFxNYQvA/clA3c6zn+OAW08aWs= X-Received: by 2002:a92:7d11:: with SMTP id y17mr4225685ilc.124.1603865643789; Tue, 27 Oct 2020 23:14:03 -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 07:13:50 +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.6 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 06:14:06 -0000 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 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. > > 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. 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. May I know your opinion, please? Thank you. -- Best regards, Tadeus