mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] Is errno signal-safe?
@ 2022-02-16 19:40 Markus Wichmann
  2022-02-16 19:56 ` Carlos O'Donell
  0 siblings, 1 reply; 4+ messages in thread
From: Markus Wichmann @ 2022-02-16 19:40 UTC (permalink / raw)
  To: musl

Hi all,

today I had a flash of inspiration while staring at some code: errno is
a global variable, right? OK, it is thread-local, but still a global
variable in the context of one thread. And looking at a global variable
while it may (or may not) be modified in a signal handler is not safe to
do.

So now I have to wonder. There are a bunch of functions that set errno,
that are on the ostensibly async-signal-safe list, like for example
write(). And to my knowledge, changes to errno are not turned back by
sigreturn(). So, are changes to errno made in a signal handler
propagated to the main program? If so, how do I inspect errno correctly
in the main program? I could block signals, but for one thing, doing so
every time errno might be relevant is going to be overkill, and for two,
if the system call I want the errno from is also blocking and I want to
allow signals while the call is blocking, there is no way to do that
without race condition.

But then again, now that I thought of it, this is so obvious that surely
someone else must have stumbled across it before, right? A solution must
exist, right?

Ciao,
Markus

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

* Re: [musl] Is errno signal-safe?
  2022-02-16 19:40 [musl] Is errno signal-safe? Markus Wichmann
@ 2022-02-16 19:56 ` Carlos O'Donell
  2022-02-16 21:01   ` Florian Weimer
  0 siblings, 1 reply; 4+ messages in thread
From: Carlos O'Donell @ 2022-02-16 19:56 UTC (permalink / raw)
  To: musl, Markus Wichmann

On 2/16/22 14:40, Markus Wichmann wrote:
> Hi all,
> 
> today I had a flash of inspiration while staring at some code: errno is
> a global variable, right? OK, it is thread-local, but still a global
> variable in the context of one thread. And looking at a global variable
> while it may (or may not) be modified in a signal handler is not safe to
> do.

It is required that errno, if changed, must be restored by the signal handler before exit
(though note that for glibc the underlying lazy TLS allocation implementation makes errno
AS-unsafe for first use in a signal handler because calloc is used to allocate the storage).
 
> So now I have to wonder. There are a bunch of functions that set errno,
> that are on the ostensibly async-signal-safe list, like for example
> write(). And to my knowledge, changes to errno are not turned back by
> sigreturn(). So, are changes to errno made in a signal handler
> propagated to the main program? If so, how do I inspect errno correctly
> in the main program? I could block signals, but for one thing, doing so
> every time errno might be relevant is going to be overkill, and for two,
> if the system call I want the errno from is also blocking and I want to
> allow signals while the call is blocking, there is no way to do that
> without race condition.

You don't need to do any of that. A correctly written signal handler must save and
restore errno or not modify it all.

It has been discussed before by both glibc and musl developers that it might be a good
idea all around to wrap signal handlers and save and restore errno in the wrapper
to avoid this entire class of problems (but this is easier said than done).

> But then again, now that I thought of it, this is so obvious that surely
> someone else must have stumbled across it before, right? A solution must
> exist, right?

It's not entirely obvious (like [1] is not always obvious), but it has been discussed and
considered, and the solution is emergent given the standards requirements :}

-- 
Cheers,
Carlos.

[1] https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/?id=dbb01cbbdb60c34a16d9d48cb58ed3680a5dd36d


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

* Re: [musl] Is errno signal-safe?
  2022-02-16 19:56 ` Carlos O'Donell
@ 2022-02-16 21:01   ` Florian Weimer
  2022-02-16 21:02     ` Carlos O'Donell
  0 siblings, 1 reply; 4+ messages in thread
From: Florian Weimer @ 2022-02-16 21:01 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: musl, Markus Wichmann

* Carlos O'Donell:

> On 2/16/22 14:40, Markus Wichmann wrote:
>> Hi all,
>> 
>> today I had a flash of inspiration while staring at some code: errno is
>> a global variable, right? OK, it is thread-local, but still a global
>> variable in the context of one thread. And looking at a global variable
>> while it may (or may not) be modified in a signal handler is not safe to
>> do.
>
> It is required that errno, if changed, must be restored by the signal
> handler before exit (though note that for glibc the underlying lazy
> TLS allocation implementation makes errno AS-unsafe for first use in a
> signal handler because calloc is used to allocate the storage).

glibc uses initial-exec TLS under the hood for storing the int variable,
so the variable access itself async-signal-safe (whether it goes
directly to errno@GLIBC_PRIVATE or via __errno_location, it doesn't
matter).

Thanks,
Florian


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

* Re: [musl] Is errno signal-safe?
  2022-02-16 21:01   ` Florian Weimer
@ 2022-02-16 21:02     ` Carlos O'Donell
  0 siblings, 0 replies; 4+ messages in thread
From: Carlos O'Donell @ 2022-02-16 21:02 UTC (permalink / raw)
  To: Florian Weimer; +Cc: musl, Markus Wichmann

On 2/16/22 16:01, Florian Weimer wrote:
> * Carlos O'Donell:
> 
>> On 2/16/22 14:40, Markus Wichmann wrote:
>>> Hi all,
>>>
>>> today I had a flash of inspiration while staring at some code: errno is
>>> a global variable, right? OK, it is thread-local, but still a global
>>> variable in the context of one thread. And looking at a global variable
>>> while it may (or may not) be modified in a signal handler is not safe to
>>> do.
>>
>> It is required that errno, if changed, must be restored by the signal
>> handler before exit (though note that for glibc the underlying lazy
>> TLS allocation implementation makes errno AS-unsafe for first use in a
>> signal handler because calloc is used to allocate the storage).
> 
> glibc uses initial-exec TLS under the hood for storing the int variable,
> so the variable access itself async-signal-safe (whether it goes
> directly to errno@GLIBC_PRIVATE or via __errno_location, it doesn't
> matter).

Thanks. I'd forgotten about that quirk. Every *other* use of non-initial-exec TLS is
still AS-unsafe.

-- 
Cheers,
Carlos.


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

end of thread, other threads:[~2022-02-16 21:03 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-16 19:40 [musl] Is errno signal-safe? Markus Wichmann
2022-02-16 19:56 ` Carlos O'Donell
2022-02-16 21:01   ` Florian Weimer
2022-02-16 21:02     ` Carlos O'Donell

Code repositories for project(s) associated with this inbox:

	https://git.vuxu.org/mirror/musl/

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 NNTP newsgroup(s).