Anonymous | Login | 2024-04-19 22:03 UTC |
Main | My View | View Issues | Change Log | Docs |
Viewing Issue Simple Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||
ID | Category | Severity | Type | Date Submitted | Last Update | ||
0000516 | [1003.1(2008)/Issue 7] System Interfaces | Objection | Omission | 2011-11-24 15:45 | 2019-06-10 08:55 | ||
Reporter | geoffclare | View Status | public | ||||
Assigned To | ajosey | ||||||
Priority | normal | Resolution | Accepted As Marked | ||||
Status | Closed | ||||||
Name | Geoff Clare | ||||||
Organization | The Open Group | ||||||
User Reference | |||||||
Section | longjmp | ||||||
Page Number | 1256 | ||||||
Line Number | 41378 | ||||||
Interp Status | Approved | ||||||
Final Accepted Text | See Note: 0001198 | ||||||
Summary | 0000516: Calling longjmp() from a signal handler | ||||||
Description |
The longjmp() page describes the following restriction on calling longjmp() from a signal handler: However, if longjmp() is invoked from a nested signal handler (that is, from a function invoked as a result of a signal raised during the handling of another signal), the behavior is undefined. There is another more obvious restriction that should be described but currently is not (except in rationale, XRAT B.2.4.3 P3515 L118392). To illustrate the problem, suppose the signal handler was called during a call to malloc() when its internal data structures were in a partly-updated state. After the longjmp() call the behaviour of any subsequent call to malloc(), realloc(), or free() would be undefined. Generalising, the restriction is that if longjmp() is called from a signal handler which interrupted a non-async-signal-safe function, the behavior of any subsequent call to a non-async-signal-safe function is undefined. Also, if the process returns from the initial call to main() this is equivalent to calling exit() (which is a non-async-signal-safe function) and so the same restriction applies. In addition, this text near the end of 2.4.3 does not properly account for [sig]longjmp() and for returning from main(): ... all functions defined by this volume of POSIX.1-2008 shall behave as defined when called from or interrupted by a signal-catching function, with a single exception: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined. and likewise for the corresponding rationale. |
||||||
Desired Action |
Change: However, if longjmp() is invoked from a nested signal handler ... to: However, if longjmp() is invoked from a signal handler which interrupted a non-async-signal-safe function or equivalent (such as the processing equivalent to exit() performed after a return from the initial call to main()), the behavior of any subsequent call to a non-async-signal-safe function or equivalent is undefined. In addition, if longjmp() is invoked from a nested signal handler ... At page 1256 line 41395 add a new paragraph to APPLICATION USAGE: It is recommended that applications do not call longjmp() or siglongjmp() from signal handlers. To avoid undefined behavior when calling these functions from a signal handler the application needs to ensure that the call is not made from a nested signal handler and also ensure one of the following two things: 1. After the call to longjmp() or siglongjmp() the process only calls async-signal-safe functions and does not return from the initial call to main(). 2. Any signal whose handler calls longjmp() or siglongjmp() is blocked during every call to a non-async-signal-safe function, and no such calls are made after returning from the initial call to main(). At page 490 line 16758 section 2.4.3 change: ... with a single exception: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined. to: ... with the exception that when a signal interrupts an unsafe function or equivalent (such as the processing equivalent to exit() performed after a return from the initial call to main()) and the signal-catching function calls an unsafe function, the behavior is undefined. Additional exceptions are specified in the descriptions of individual functions such as longjmp(). Cross-volume change to XRAT ... At page 3515 line 118400 section B.2.4.3 change: POSIX.1 does not define the behavior when any unsafe function is called in a signal handler that interrupts any unsafe function. to: POSIX.1 does not define the behavior when any unsafe function is called in (or after a longjmp() out of) a signal handler that interrupts any unsafe function or the non-async-signal-safe processing equivalent to exit() that is performed after return from the initial call to main(). |
||||||
Tags | tc2-2008 | ||||||
Attached Files | |||||||
|
Notes | |
(0001053) Konrad_Schwarz (reporter) 2011-11-25 08:35 |
I consider this defect report unnecessary. As [sig]longjmp is not on the list of async-signal-safe functions, the standard does not allow it to be called _without restriction_ from a signal handler. As with other "unsafe" functions, it is perfectly OK, from the point of view of the standard, to call [sig]longjmp when it is known that the signal did not interrupt some other unsafe function. Of course the _application_ must ensure that _it_ can properly unwind whatever operation was in progress; but this is always the case when using longjmp, irrespective of whether it is being called from a signal handler. I'm not sure why the added text discusses processing from exit: if an atexit handler raises a signal, why can't a signal handler longjmp to a setjmp'd location in that atexit handler? The case of an asynchronous signal, such as SIGALRM, jumping back to somewhere within main, is already handled by longjmp: If the function containing the invocation of setjmp() has terminated execution in the interim, or if the invocation of setjmp() was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined. System-defined exit processing must not generate any signals, given a fully conforming application. In the proposed APPLICATION USAGE, item 1: 1. After the call to longjmp() or siglongjmp() the process only calls async-signal-safe functions and does not return from the initial call to main(). is an extension to the current standard: currently siglongjmp() called from a signal handler interrupting an unsafe function leads to undefined behavior; this APPLICATION USAGE changes that. I don't think you want that. Item 2 of APPLICATION USAGE is one way of ensuring what the standard already says: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined. However, other ways exist, e.g., for a synchronous exception like SIGSEGV, passing proper arguments to standard functions ensures they won't generate the signal. (Passing incorrect arguments is already undefined). Thus, the phrase "also ensure one of the following two things" is wrong. I think it would be perfectly acceptable to leave the current, concise wording on pg. 490: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined. Honestly, I think the proposed wording just muddles the issue. At most, I would add a note that [sig]longjmp is an unsafe function. Similarly, the XRAT change. As [sig]longjmp() is an usafe function, it does not need to be treated specially. |
(0001070) geoffclare (manager) 2011-11-30 15:57 |
Discussions on the mailing list have identified two additional issues: 1. The restriction on calling longjmp() from a nested signal handler derives from C90 and is felt not to be necessary on POSIX systems. We could remove it. 2. Section 2.4.3 conflicts with the longjmp() description. It says, after the table of async-signal-safe functions: All functions not in the above table are considered to be unsafe with respect to signals. Thus all functions are either safe or unsafe; it does not allow for functions that are "safe but with restrictions". Two possible solutions are: A. Modify 2.4.3 so that it allows for functions that are "safe but with restrictions". B. Modify the longjmp() description so that it says something like: ... longjmp() shall execute correctly in contexts of interrupts, signals, and any of their associated functions, provided the interrupt did not occur during a call to a non-async-signal-safe function. Option A more closely represents the situation that exists on current implementations, and I believe it is probably what the standard originally intended for longjmp(). Option B would greatly restrict the use of longjmp() from signal handlers, and would, as pointed out in Note: 0001053 (which presupposes option B), make much of the desired action unnecessary. Once the group decides which way to go on these two issues, I will propose a revised set of changes. |
(0001195) geoffclare (manager) 2012-04-11 10:59 edited on: 2012-04-12 09:10 |
This is a revised proposal following the decision in the 5th April teleconference to remove the nested signal handler restriction and to modify 2.4.3 so that it allows longjmp() to be "safe but with restrictions". (It does the latter without introducing a third signal safety category, since the nested restriction is removed. Instead it adds longjmp() and siglongjmp() to the async-signal-safe list and specifies that although calls to async-signal-safe functions can be made from signal-catching functions without restriction, for certain functions there are restrictions on subsequent behaviour.) At page 1256 line 41377 section longjmp() change: As it bypasses the usual function call and return mechanisms, longjmp() shall execute correctly in contexts of interrupts, signals, and any of their associated functions. However, if longjmp() is invoked from a nested signal handler (that is, from a function invoked as a result of a signal raised during the handling of another signal), the behavior is undefined. to: Although longjmp() is an async-signal-safe function, if it is invoked from a signal handler which interrupted a non-async-signal-safe function or equivalent (such as the processing equivalent to exit() performed after a return from the initial call to main()), the behavior of any subsequent call to a non-async-signal-safe function or equivalent is undefined. At page 1256 line 41395 add a new paragraph to APPLICATION USAGE: It is recommended that applications do not call longjmp() or siglongjmp() from signal handlers. To avoid undefined behavior when calling these functions from a signal handler the application needs to ensure one of the following two things: 1. After the call to longjmp() or siglongjmp() the process only calls async-signal-safe functions and does not return from the initial call to main(). 2. Any signal whose handler calls longjmp() or siglongjmp() is blocked during every call to a non-async-signal-safe function, and no such calls are made after returning from the initial call to main(). At page 489 line 16721 section 2.4.3 change: Therefore, applications can invoke them, without restriction, from signal-catching functions: to: Therefore, applications can call them, without restriction, from signal-catching functions. Note that, although there is no restriction on the calls themselves, for certain functions there are restrictions on subsequent behavior after the function is called from a signal-catching function (see [xref to longjmp()]). At page 489 line 16722-16755 section 2.4.3 add longjmp() and siglongjmp() to the table of async-signal-safe functions. At page 490 line 16758 section 2.4.3 change: ... with a single exception: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined. to: ... with the exception that when a signal interrupts an unsafe function or equivalent (such as the processing equivalent to exit() performed after a return from the initial call to main()) and the signal-catching function calls an unsafe function, the behavior is undefined. Additional exceptions are specified in the descriptions of individual functions such as longjmp(). Cross-volume change to XBD ... At page 37 line 1229 section 3.27 change the definition of Async-Signal-Safe Function from: A function that may be invoked, without restriction, from signal-catching functions. No function is async-signal-safe unless explicitly described as such. to: A function that can be called, without restriction, from signal-catching functions. Note that, although there is no restriction on the calls themselves, for certain functions there are restrictions on subsequent behavior after the function is called from a signal-catching function. No function is async-signal-safe unless explicitly described as such. Note: Async-signal-safety is defined in detail in [xref to XSH 2.4.3]. Cross-volume changes to XRAT ... At page 3514 line 118375 section B.2.4.3 change: The behavior of unsafe functions, as defined by this section, is undefined when they are invoked from signal-catching functions in certain circumstances. to: The behavior of unsafe functions, as defined by this section, is undefined when they are called from (or after a longjmp() or siglongjmp() out of) signal-catching functions in certain circumstances. At page 3515 line 118392 section B.2.4.3 change: Note that longjmp() and siglongjmp() are not in the list of async-signal-safe functions. to: Note that although longjmp() and siglongjmp() are in the list of async-signal-safe functions, there are restrictions on subsequent behavior after the function is called from a signal-catching function. At page 3515 line 118400 section B.2.4.3 change: POSIX.1 does not define the behavior when any unsafe function is called in a signal handler that interrupts any unsafe function. to: POSIX.1 does not define the behavior when any unsafe function is called in (or after a longjmp() or siglongjmp() out of) a signal handler that interrupts any unsafe function or the non-async-signal-safe processing equivalent to exit() that is performed after return from the initial call to main(). |
(0001198) Don Cragun (manager) 2012-04-12 15:51 edited on: 2012-04-12 15:54 |
Interpretation response ------------------------ The standard is unclear on this issue, and no conformance distinction can be made between alternative implementations based on this. This is being referred to the sponsor. Rationale: ------------- The restrictions on using longjmp() and siglongjmp() are more restrictive than they need to be on POSIX systems. The loosened restrictions presented here do not break existing implementations and make it easier for application writers to create portable applications. Notes to the Editor (not part of this interpretation): ------------------------------------------------------- Make the changes presented in Note: 0001195 |
(0001293) ajosey (manager) 2012-06-29 16:17 |
Interpretation proposed 29 June 2012 for final 45 day review |
(0001356) ajosey (manager) 2012-08-30 09:15 |
Interpretation approved 30 Aug 2012 |
(0003067) dalias (reporter) 2016-02-07 01:41 |
The approved text is written from a standpoint that ignores the existence of threads. For instance it refers to returning from the initial invocation of main, but not returning from the thread start function for a non-initial thread, which would be just as unsafe (equivalent to pthread_exit, which is unsafe, and virtually impossible to implement safely). I believe this needs further review. |
(0003069) shware_systems (reporter) 2016-02-07 19:18 edited on: 2016-02-07 19:19 |
I think this clause in setjmp() is intended to cover that: "If the most recent invocation of setjmp() with the corresponding jmp_buf occurred in another thread, or if there is no such invocation, or if the function containing the invocation of setjmp() has terminated execution in the interim, or if the invocation of setjmp() was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined." where "if the (thread) function containing the invocation..." includes via pthread_exit() call or return at closing brace. I believe returning from main() is special, or any _Noreturn qualified interface, as the entire process is going zombie and may be invalidating what a thread considers static, as well as automatic, variables the jmp_buf references of the process state, including the structures managing active additional threads. |
(0003070) dalias (reporter) 2016-02-07 21:25 |
The reason returning from main is considered as special is that the effect is the same as calling exit. The exit function is AS-unsafe, so already covered by the general language that forbids calling AS-unsafe functions after such a longjmp, but returning from the initial invocation of main is not, in the abstract machine, a "call" to exit, despite likely being implemented as such, and thus requires a special case. A large part of what exit does requires locking and access to global data structures that cannot be made AS-safe in any reasonable way. My point is that the same applies to return from the initial thread function for non-initial threads - returning is equivalent to (and likely implemented as) a call to pthread_exit, which is AS-unsafe, and which is required to perform a number of actions that cannot be made AS-safe in any reasonable way. The language about calling AS-unsafe function "after" longjmp out of a signal handler is also imprecise in the context of a multithreaded program where the concept of "after" is not well-defined except within a single thread or in the presence of synchronization that imposes an order between actions by different threads. In particular, consider the case where thread A performs a longjmp out of a signal handler that interrupted an AS-unsafe function concurrently with thread B making calls to AS-unsafe functions. This should NOT result in undefined behavior, even if the calls in thread B happen "after" the longjmp in thread A; such an "after" relationship can be established by having thread A call sem_post (which is AS-safe) or synchronize via pipes or other AS-safe mechanisms after the longjmp. Such calls in thread B may stall waiting for a lock that was held by the interrupted AS-unsafe function in thread A, but that can happen anyway if the signal handler does not return; longjmp in itself is not the cause of the stall. |
(0003071) geoffclare (manager) 2016-02-08 09:46 |
The thread return case is already covered in the new normative text because it says "interrupted a non-async-signal-safe function or equivalent" and just gives the return from main() as an example of something that is equivalent to calling a non-async-signal-safe function. However, it may be worth including references to this case in the non-normative application usage and rationale additions. The new text is in TC2 draft 3 which is going to start review on Feb 19; the appropriate way to request an update to these additions would be to submit a new bug against the 2008-TC2 project, specifying the version as draft 3. |
(0003072) shware_systems (reporter) 2016-02-08 12:11 |
If a system allows the thread context to change before a signal function returns, normally or via a longjmp, it is up to it to manage any potential conflicts, as part of "unspecified" in what I cited. A system that doesn't allow switches to another thread, whether scheduling is preemptive or not, has "after" well-defined as a consequence. I said intended to point out that threading concerns aren't ignored by the interfaces, but I agree more could specified regardless of scheduling policy. Items like pipe handles are usually stored in effectively static arrays of the process state, accessible to any thread of the process by some method, not necessarily declared static. |
Issue History | |||
Date Modified | Username | Field | Change |
2011-11-24 15:45 | geoffclare | New Issue | |
2011-11-24 15:45 | geoffclare | Status | New => Under Review |
2011-11-24 15:45 | geoffclare | Assigned To | => ajosey |
2011-11-24 15:45 | geoffclare | Name | => Geoff Clare |
2011-11-24 15:45 | geoffclare | Organization | => The Open Group |
2011-11-24 15:45 | geoffclare | Section | => longjmp |
2011-11-24 15:45 | geoffclare | Page Number | => 1256 |
2011-11-24 15:45 | geoffclare | Line Number | => 41378 |
2011-11-24 15:45 | geoffclare | Interp Status | => --- |
2011-11-25 08:35 | Konrad_Schwarz | Note Added: 0001053 | |
2011-11-30 15:57 | geoffclare | Note Added: 0001070 | |
2012-04-11 10:59 | geoffclare | Note Added: 0001195 | |
2012-04-12 09:10 | geoffclare | Note Edited: 0001195 | |
2012-04-12 15:51 | Don Cragun | Note Added: 0001198 | |
2012-04-12 15:52 | Don Cragun | Interp Status | --- => Pending |
2012-04-12 15:52 | Don Cragun | Final Accepted Text | => See bugnote:11894 |
2012-04-12 15:52 | Don Cragun | Status | Under Review => Interpretation Required |
2012-04-12 15:52 | Don Cragun | Resolution | Open => Accepted As Marked |
2012-04-12 15:52 | Don Cragun | Tag Attached: tc2-2008 | |
2012-04-12 15:53 | Don Cragun | Final Accepted Text | See bugnote:11894 => See Note: 0001198 |
2012-04-12 15:54 | Don Cragun | Note Edited: 0001198 | |
2012-06-29 16:17 | ajosey | Interp Status | Pending => Proposed |
2012-06-29 16:17 | ajosey | Note Added: 0001293 | |
2012-08-30 09:15 | ajosey | Interp Status | Proposed => Approved |
2012-08-30 09:15 | ajosey | Note Added: 0001356 | |
2016-02-07 01:41 | dalias | Note Added: 0003067 | |
2016-02-07 19:18 | shware_systems | Note Added: 0003069 | |
2016-02-07 19:19 | shware_systems | Note Edited: 0003069 | |
2016-02-07 21:25 | dalias | Note Added: 0003070 | |
2016-02-08 09:46 | geoffclare | Note Added: 0003071 | |
2016-02-08 12:11 | shware_systems | Note Added: 0003072 | |
2019-06-10 08:55 | agadmin | Status | Interpretation Required => Closed |
Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group |