Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000807 [1003.1(2013)/Issue7+TC1] Base Definitions and Headers Comment Clarification Requested 2013-12-04 10:35 2019-06-10 08:55
Reporter Florian Weimer View Status public  
Assigned To
Priority normal Resolution Accepted As Marked  
Status Closed  
Name Florian Weimer
Organization Red Hat, Inc.
User Reference
Section 2.4
Page Number 31
Line Number 1119-1126
Interp Status ---
Final Accepted Text See Note: 0002111
Summary 0000807: Interaction between errno and signal handlers
Description Section 2.4.3 indicates that setting errno is async-signal-safe. Section 2.4.4 has this:

"If the action of the signal is to invoke a signal-catching function, the signal-catching function shall be invoked; in this case the original function is said to be "interrupted" by the signal. If the signal-catching function executes a return statement, the behavior of the interrupted function shall be as described individually for that function, except as noted for unsafe functions."

<http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_04> [^]

The combination of these two requirements suggest to me that implementations either should not rely on errno-based error handling internally, or restore errno upon exit from signal handlers.

The sigaction specification suggests that manual restoring of errno in the signal handler is required: <http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html#tag_16_540_07> [^] But this step should not be necessary if setting errno is async-signal-safe (as discussed above).

Few applications properly save and restore errno in their signal handlers, introducing spurious failure conditions, so we're contemplating a change to do this automatically and globally.
Desired Action Clarify if it is permitted to restore the value of errno upon return from a signal handler, so that any change of errno in a signal handler is automatically confined to it.
Tags tc2-2008
Attached Files

- Relationships

-  Notes
(0002039)
Florian Weimer (reporter)
2013-12-04 10:48

Or alternatively, clarify that programs may use errno as a communication mechanism with a signal handler, setting it in a signal handler, and reading it from the interrupted program code.
(0002040)
geoffclare (manager)
2013-12-04 11:27

There seems to be some misunderstanding of what it means for setting
errno to be async-signal-safe (as far as POSIX is concerned). All it
means is that applications can set errno in signal handlers, without
restriction.

I can't see any way to derive an implication that "implementations
either should not rely on errno-based error handling internally, or
restore errno upon exit from signal handlers" from that.

The only reason obtaining and setting the value of errno are required
to be async-signal-safe by POSIX is because applications need to be
able to save and restore it in signal handlers.

In answer to the desired action: as far as I can see, the standard
is silent as regards whether implementations are allowed to restore
errno automatically on return from signal handlers. This means
implementations are free to do so if they want to, but portable
applications cannot rely on it and should restore errno themselves.

I doubt very much if any applications exist that expect to be able to
set errno in a signal handler and obtain the value in the interrupted
code. In order for this to be reliable it would need to ensure that
the signal handler never interrupts a call to a function that might
set errno.

If we make any change as a result of this issue, I think it should
just be to make it explicit that implementations are allowed, but
not required, to restore errno on return from signal handlers.
(0002041)
joerg (reporter)
2013-12-04 12:13

I believe we should discuss which "errno" is affected when
a signal handler contains errno = 123 or when a syscall from
the signal handler fails.

The man page for kill() does not mention how the signal
is delivered, except when kill() sends a signal to the same
process (e.g. whether it is granted to be delivered
to the main thread for all other cases).
(0002042)
shware_systems (reporter)
2013-12-04 21:55

Re: 002040:
"If we make any change as a result of this issue, I think it should
just be to make it explicit that implementations are allowed, but
not required, to restore errno on return from signal handlers. "

Per XSH 2.3, the thread scheduler is supposed to save the errno value on switching to a new thread. I don't see where the standard blocks that a preemptive scheduler may switch to a new active thread while a signal handler is executing. As basic handlers set by signal() are per process, any errno change done in the handler may be overwritten by the scheduler as part of the handler return procedure, especially where a higher priority thread is in a wait state on a particular signal so gets unblocked after delivery. For handlers set by sigaction() with SA_RESTART in effect, any modification to errno risks being undone anyways as it can be construed that the value of errno must also be saved and restored in that thread context so the same conditions when the interrupted interface did start pertain again. While not enough to say its required 'all the time', there is evidence for some circumstances it is required already, not just allowed.
(0002043)
dalias (reporter)
2013-12-04 22:16

shware_systems, XSH 2.3 specifies no such thing as "switching to a new thread" or saving the value of errno. An implementation which has a single errno object with external storage at a fixed address, and which only permits one thread to run at a time, and saves and restores the value of errno when switching threads, *seems* to conform to the requirements of this issue of POSIX, but it does not conform to C11 which requires errno to have thread storage duration. (In particular, &errno evaluating to the same address for each thread does not seem to conform to C11 requirements.) I'm quite aware that POSIX is not yet aligned with C11, but the C11 requirements on errno are *consistent* with POSIX, i.e. having errno with thread-local storage is perfectly conforming to the current POSIX requirements. As such, I think your reasoning is based merely on your idea of one possible (and, in my opinion outdated) implementation of errno, not any requirements.
(0002044)
shware_systems (reporter)
2013-12-05 06:56

XSH 2.3 has "For each thread of a process, the value of errno shall not be affected by function calls or assignments to errno by other threads.", Line 16306.
Yes, how I put it is more backwards compatible as a worst case of conforming than forwards and is inherently less robust. C11 doesn't fix this entirely either, even for multi-core CPUs when there's more threads than cores, but it does make it less likely problems will surface due to data races. The point is more that a multi-threaded application can not rely on errno as a communication mechanism, I agree with geoff there, but there's at least one case with POSIX where it looks like the signal return is already required to restore errno or risk some interfaces being unreliable, so I don't agree there. The getgrgid() interface is an example where errno on restart is significant, as the application is required to clear errno to distinguish the 'not found' case.
(0002045)
geoffclare (manager)
2013-12-05 09:45

It's true that if getgrgid() is interrupted, a function call from the
signal handler changes errno, and the getgrgid() call is restarted,
then if the implementation does not restore errno the application
could mistakenly treat a "not found" null return as an error.

However, my reading of the standard is that the onus is not on the
implementation to prevent this from happening. It is just another
reason why applications should save and restore errno in signal
handlers.
(0002046)
shware_systems (reporter)
2013-12-05 13:51

As a signal may be interrupting an interface that isn't restart sensitive, the practice of saving and restoring errno is still a good idea but may be superfluous. sigaction() does not mention any requirements about saving any state in the handler that the application need account for, similar to it being explicit setting errno to 0 is needed in some cases. Because of that I look on it as the interfaces that may be restarted are what know the state that has to be saved so the restart succeeds, as that's implementation specific in how the interface is programmed. An application doesn't know about undocumented internal state that might also need saving, such as the fields used for managing timeouts that may be adjusted, so can't account for them in a handler.

The responsibility is more on those interfaces than the signal dispatcher and return processing to set things up properly in case a signal is delivered, to restart or abort, but I can't see putting any onus on the application that could be considered portable. This includes for those that rely on errno, as what the value for errno is on interface entry may differ from a pending errno value at the time a signal is delivered, and that may require a rollback of state before the restart.
(0002047)
dalias (reporter)
2013-12-05 15:18

In regards to notes 0002045 and 0002046, I think it should be clarified somewhere (XSH 2.4.3?) that changing errno in a signal handler without restoring it before returning can cause problems to the interrupted code. My preference would be to declare the behavior completely undefined. This would explicitly permit implementations that DO restore errno (like glibc has proposed doing) and clarify that all historical implementations (which do not restore errno) are conforming.
(0002111)
Florian Weimer (reporter)
2014-01-22 16:16

Here's a proposal for a wording change.

Section 2.4.3:

Replace

| Operations which obtain the value of errno and operations which assign a value to errno shall be async-signal-safe.

with:

| Operations which obtain the value of errno and operations which assign a value to errno shall be async-signal-safe, provided that the signal-catching function saves the value of errno upon entry and restores it before it returns.

Section 2.4.4:

After

| except as noted for unsafe functions.

insert this setence:

| After returning from a signal-catching function, the value of errno is unspecified if the signal-catching function or any function it called assigned a value to errno and the signal-catching function did not save and restore the original value of errno.

- Issue History
Date Modified Username Field Change
2013-12-04 10:35 Florian Weimer New Issue
2013-12-04 10:35 Florian Weimer Name => Florian Weimer
2013-12-04 10:35 Florian Weimer Organization => Red Hat, Inc.
2013-12-04 10:35 Florian Weimer Section => 2.4
2013-12-04 10:48 Florian Weimer Note Added: 0002039
2013-12-04 10:49 Florian Weimer Issue Monitored: Florian Weimer
2013-12-04 11:27 geoffclare Note Added: 0002040
2013-12-04 12:13 joerg Note Added: 0002041
2013-12-04 21:55 shware_systems Note Added: 0002042
2013-12-04 22:16 dalias Note Added: 0002043
2013-12-05 06:56 shware_systems Note Added: 0002044
2013-12-05 09:45 geoffclare Note Added: 0002045
2013-12-05 13:51 shware_systems Note Added: 0002046
2013-12-05 15:18 dalias Note Added: 0002047
2014-01-22 16:16 Florian Weimer Note Added: 0002111
2014-02-27 16:42 Don Cragun Page Number => 31
2014-02-27 16:42 Don Cragun Line Number => 1119-1126
2014-02-27 16:42 Don Cragun Interp Status => ---
2014-02-27 16:42 Don Cragun Final Accepted Text => See Note: 0002111
2014-02-27 16:42 Don Cragun Status New => Resolved
2014-02-27 16:42 Don Cragun Resolution Open => Accepted As Marked
2014-02-27 16:42 Don Cragun Tag Attached: tc2-2008
2019-06-10 08:55 agadmin Status Resolved => Closed


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker