diff options
Diffstat (limited to 'manual/setjmp.texi')
-rw-r--r-- | manual/setjmp.texi | 496 |
1 files changed, 0 insertions, 496 deletions
diff --git a/manual/setjmp.texi b/manual/setjmp.texi deleted file mode 100644 index 94d16becdc..0000000000 --- a/manual/setjmp.texi +++ /dev/null @@ -1,496 +0,0 @@ -@node Non-Local Exits, Signal Handling, Resource Usage And Limitation, Top -@c %MENU% Jumping out of nested function calls -@chapter Non-Local Exits -@cindex non-local exits -@cindex long jumps - -Sometimes when your program detects an unusual situation inside a deeply -nested set of function calls, you would like to be able to immediately -return to an outer level of control. This section describes how you can -do such @dfn{non-local exits} using the @code{setjmp} and @code{longjmp} -functions. - -@menu -* Intro: Non-Local Intro. When and how to use these facilities. -* Details: Non-Local Details. Functions for non-local exits. -* Non-Local Exits and Signals:: Portability issues. -* System V contexts:: Complete context control a la System V. -@end menu - -@node Non-Local Intro, Non-Local Details, , Non-Local Exits -@section Introduction to Non-Local Exits - -As an example of a situation where a non-local exit can be useful, -suppose you have an interactive program that has a ``main loop'' that -prompts for and executes commands. Suppose the ``read'' command reads -input from a file, doing some lexical analysis and parsing of the input -while processing it. If a low-level input error is detected, it would -be useful to be able to return immediately to the ``main loop'' instead -of having to make each of the lexical analysis, parsing, and processing -phases all have to explicitly deal with error situations initially -detected by nested calls. - -(On the other hand, if each of these phases has to do a substantial -amount of cleanup when it exits---such as closing files, deallocating -buffers or other data structures, and the like---then it can be more -appropriate to do a normal return and have each phase do its own -cleanup, because a non-local exit would bypass the intervening phases and -their associated cleanup code entirely. Alternatively, you could use a -non-local exit but do the cleanup explicitly either before or after -returning to the ``main loop''.) - -In some ways, a non-local exit is similar to using the @samp{return} -statement to return from a function. But while @samp{return} abandons -only a single function call, transferring control back to the point at -which it was called, a non-local exit can potentially abandon many -levels of nested function calls. - -You identify return points for non-local exits by calling the function -@code{setjmp}. This function saves information about the execution -environment in which the call to @code{setjmp} appears in an object of -type @code{jmp_buf}. Execution of the program continues normally after -the call to @code{setjmp}, but if an exit is later made to this return -point by calling @code{longjmp} with the corresponding @w{@code{jmp_buf}} -object, control is transferred back to the point where @code{setjmp} was -called. The return value from @code{setjmp} is used to distinguish -between an ordinary return and a return made by a call to -@code{longjmp}, so calls to @code{setjmp} usually appear in an @samp{if} -statement. - -Here is how the example program described above might be set up: - -@smallexample -@include setjmp.c.texi -@end smallexample - -The function @code{abort_to_main_loop} causes an immediate transfer of -control back to the main loop of the program, no matter where it is -called from. - -The flow of control inside the @code{main} function may appear a little -mysterious at first, but it is actually a common idiom with -@code{setjmp}. A normal call to @code{setjmp} returns zero, so the -``else'' clause of the conditional is executed. If -@code{abort_to_main_loop} is called somewhere within the execution of -@code{do_command}, then it actually appears as if the @emph{same} call -to @code{setjmp} in @code{main} were returning a second time with a value -of @code{-1}. - -@need 250 -So, the general pattern for using @code{setjmp} looks something like: - -@smallexample -if (setjmp (@var{buffer})) - /* @r{Code to clean up after premature return.} */ - @dots{} -else - /* @r{Code to be executed normally after setting up the return point.} */ - @dots{} -@end smallexample - -@node Non-Local Details, Non-Local Exits and Signals, Non-Local Intro, Non-Local Exits -@section Details of Non-Local Exits - -Here are the details on the functions and data structures used for -performing non-local exits. These facilities are declared in -@file{setjmp.h}. -@pindex setjmp.h - -@comment setjmp.h -@comment ISO -@deftp {Data Type} jmp_buf -Objects of type @code{jmp_buf} hold the state information to -be restored by a non-local exit. The contents of a @code{jmp_buf} -identify a specific place to return to. -@end deftp - -@comment setjmp.h -@comment ISO -@deftypefn Macro int setjmp (jmp_buf @var{state}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} -@c _setjmp ok -@c __sigsetjmp(!savemask) ok -@c __sigjmp_save(!savemask) ok, does not call sigprocmask -When called normally, @code{setjmp} stores information about the -execution state of the program in @var{state} and returns zero. If -@code{longjmp} is later used to perform a non-local exit to this -@var{state}, @code{setjmp} returns a nonzero value. -@end deftypefn - -@comment setjmp.h -@comment ISO -@deftypefun void longjmp (jmp_buf @var{state}, int @var{value}) -@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{} @asucorrupt{} @asulock{/hurd}}@acunsafe{@acucorrupt{} @aculock{/hurd}}} -@c __libc_siglongjmp @ascuplugin @asucorrupt @asulock/hurd @acucorrupt @aculock/hurd -@c _longjmp_unwind @ascuplugin @asucorrupt @acucorrupt -@c __pthread_cleanup_upto @ascuplugin @asucorrupt @acucorrupt -@c plugins may be unsafe themselves, but even if they weren't, this -@c function isn't robust WRT async signals and cancellation: -@c cleanups aren't taken off the stack right away, only after all -@c cleanups have been run. This means that async-cancelling -@c longjmp, or interrupting longjmp with an async signal handler -@c that calls longjmp may run the same cleanups multiple times. -@c _JMPBUF_UNWINDS_ADJ ok -@c *cleanup_buf->__routine @ascuplugin -@c sigprocmask(SIG_SETMASK) dup @asulock/hurd @aculock/hurd -@c __longjmp ok -This function restores current execution to the state saved in -@var{state}, and continues execution from the call to @code{setjmp} that -established that return point. Returning from @code{setjmp} by means of -@code{longjmp} returns the @var{value} argument that was passed to -@code{longjmp}, rather than @code{0}. (But if @var{value} is given as -@code{0}, @code{setjmp} returns @code{1}).@refill -@end deftypefun - -There are a lot of obscure but important restrictions on the use of -@code{setjmp} and @code{longjmp}. Most of these restrictions are -present because non-local exits require a fair amount of magic on the -part of the C compiler and can interact with other parts of the language -in strange ways. - -The @code{setjmp} function is actually a macro without an actual -function definition, so you shouldn't try to @samp{#undef} it or take -its address. In addition, calls to @code{setjmp} are safe in only the -following contexts: - -@itemize @bullet -@item -As the test expression of a selection or iteration -statement (such as @samp{if}, @samp{switch}, or @samp{while}). - -@item -As one operand of an equality or comparison operator that appears as the -test expression of a selection or iteration statement. The other -operand must be an integer constant expression. - -@item -As the operand of a unary @samp{!} operator, that appears as the -test expression of a selection or iteration statement. - -@item -By itself as an expression statement. -@end itemize - -Return points are valid only during the dynamic extent of the function -that called @code{setjmp} to establish them. If you @code{longjmp} to -a return point that was established in a function that has already -returned, unpredictable and disastrous things are likely to happen. - -You should use a nonzero @var{value} argument to @code{longjmp}. While -@code{longjmp} refuses to pass back a zero argument as the return value -from @code{setjmp}, this is intended as a safety net against accidental -misuse and is not really good programming style. - -When you perform a non-local exit, accessible objects generally retain -whatever values they had at the time @code{longjmp} was called. The -exception is that the values of automatic variables local to the -function containing the @code{setjmp} call that have been changed since -the call to @code{setjmp} are indeterminate, unless you have declared -them @code{volatile}. - -@node Non-Local Exits and Signals, System V contexts, Non-Local Details, Non-Local Exits -@section Non-Local Exits and Signals - -In BSD Unix systems, @code{setjmp} and @code{longjmp} also save and -restore the set of blocked signals; see @ref{Blocking Signals}. However, -the POSIX.1 standard requires @code{setjmp} and @code{longjmp} not to -change the set of blocked signals, and provides an additional pair of -functions (@code{sigsetjmp} and @code{siglongjmp}) to get the BSD -behavior. - -The behavior of @code{setjmp} and @code{longjmp} in @theglibc{} is -controlled by feature test macros; see @ref{Feature Test Macros}. The -default in @theglibc{} is the POSIX.1 behavior rather than the BSD -behavior. - -The facilities in this section are declared in the header file -@file{setjmp.h}. -@pindex setjmp.h - -@comment setjmp.h -@comment POSIX.1 -@deftp {Data Type} sigjmp_buf -This is similar to @code{jmp_buf}, except that it can also store state -information about the set of blocked signals. -@end deftp - -@comment setjmp.h -@comment POSIX.1 -@deftypefun int sigsetjmp (sigjmp_buf @var{state}, int @var{savesigs}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{/hurd}}@acunsafe{@aculock{/hurd}}} -@c sigsetjmp @asulock/hurd @aculock/hurd -@c __sigsetjmp(savemask) @asulock/hurd @aculock/hurd -@c __sigjmp_save(savemask) @asulock/hurd @aculock/hurd -@c sigprocmask(SIG_BLOCK probe) dup @asulock/hurd @aculock/hurd -This is similar to @code{setjmp}. If @var{savesigs} is nonzero, the set -of blocked signals is saved in @var{state} and will be restored if a -@code{siglongjmp} is later performed with this @var{state}. -@end deftypefun - -@comment setjmp.h -@comment POSIX.1 -@deftypefun void siglongjmp (sigjmp_buf @var{state}, int @var{value}) -@safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{} @asucorrupt{} @asulock{/hurd}}@acunsafe{@acucorrupt{} @aculock{/hurd}}} -@c Alias to longjmp. -This is similar to @code{longjmp} except for the type of its @var{state} -argument. If the @code{sigsetjmp} call that set this @var{state} used a -nonzero @var{savesigs} flag, @code{siglongjmp} also restores the set of -blocked signals. -@end deftypefun - -@node System V contexts,, Non-Local Exits and Signals, Non-Local Exits -@section Complete Context Control - -The Unix standard provides one more set of functions to control the -execution path and these functions are more powerful than those -discussed in this chapter so far. These functions were part of the -original @w{System V} API and by this route were added to the Unix -API. Besides on branded Unix implementations these interfaces are not -widely available. Not all platforms and/or architectures @theglibc{} -is available on provide this interface. Use @file{configure} to -detect the availability. - -Similar to the @code{jmp_buf} and @code{sigjmp_buf} types used for the -variables to contain the state of the @code{longjmp} functions the -interfaces of interest here have an appropriate type as well. Objects -of this type are normally much larger since more information is -contained. The type is also used in a few more places as we will see. -The types and functions described in this section are all defined and -declared respectively in the @file{ucontext.h} header file. - -@comment ucontext.h -@comment SVID -@deftp {Data Type} ucontext_t - -The @code{ucontext_t} type is defined as a structure with at least the -following elements: - -@table @code -@item ucontext_t *uc_link -This is a pointer to the next context structure which is used if the -context described in the current structure returns. - -@item sigset_t uc_sigmask -Set of signals which are blocked when this context is used. - -@item stack_t uc_stack -Stack used for this context. The value need not be (and normally is -not) the stack pointer. @xref{Signal Stack}. - -@item mcontext_t uc_mcontext -This element contains the actual state of the process. The -@code{mcontext_t} type is also defined in this header but the definition -should be treated as opaque. Any use of knowledge of the type makes -applications less portable. - -@end table -@end deftp - -Objects of this type have to be created by the user. The initialization -and modification happens through one of the following functions: - -@comment ucontext.h -@comment SVID -@deftypefun int getcontext (ucontext_t *@var{ucp}) -@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@assafe{}@acsafe{}} -@c Linux-only implementations in assembly, including sigprocmask -@c syscall. A few cases call the sigprocmask function, but that's safe -@c too. The ppc case is implemented in terms of a swapcontext syscall. -The @code{getcontext} function initializes the variable pointed to by -@var{ucp} with the context of the calling thread. The context contains -the content of the registers, the signal mask, and the current stack. -Executing the contents would start at the point where the -@code{getcontext} call just returned. - -The function returns @code{0} if successful. Otherwise it returns -@code{-1} and sets @var{errno} accordingly. -@end deftypefun - -The @code{getcontext} function is similar to @code{setjmp} but it does -not provide an indication of whether @code{getcontext} is returning for -the first time or whether an initialized context has just been restored. -If this is necessary the user has to determine this herself. This must -be done carefully since the context contains registers which might contain -register variables. This is a good situation to define variables with -@code{volatile}. - -Once the context variable is initialized it can be used as is or it can -be modified using the @code{makecontext} function. The latter is normally -done when implementing co-routines or similar constructs. - -@comment ucontext.h -@comment SVID -@deftypefun void makecontext (ucontext_t *@var{ucp}, void (*@var{func}) (void), int @var{argc}, @dots{}) -@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@assafe{}@acsafe{}} -@c Linux-only implementations mostly in assembly, nothing unsafe. - -The @var{ucp} parameter passed to @code{makecontext} shall be -initialized by a call to @code{getcontext}. The context will be -modified in a way such that if the context is resumed it will start by -calling the function @code{func} which gets @var{argc} integer arguments -passed. The integer arguments which are to be passed should follow the -@var{argc} parameter in the call to @code{makecontext}. - -Before the call to this function the @code{uc_stack} and @code{uc_link} -element of the @var{ucp} structure should be initialized. The -@code{uc_stack} element describes the stack which is used for this -context. No two contexts which are used at the same time should use the -same memory region for a stack. - -The @code{uc_link} element of the object pointed to by @var{ucp} should -be a pointer to the context to be executed when the function @var{func} -returns or it should be a null pointer. See @code{setcontext} for more -information about the exact use. -@end deftypefun - -While allocating the memory for the stack one has to be careful. Most -modern processors keep track of whether a certain memory region is -allowed to contain code which is executed or not. Data segments and -heap memory are normally not tagged to allow this. The result is that -programs would fail. Examples for such code include the calling -sequences the GNU C compiler generates for calls to nested functions. -Safe ways to allocate stacks correctly include using memory on the -original thread's stack or explicitly allocating memory tagged for -execution using (@pxref{Memory-mapped I/O}). - -@strong{Compatibility note}: The current Unix standard is very imprecise -about the way the stack is allocated. All implementations seem to agree -that the @code{uc_stack} element must be used but the values stored in -the elements of the @code{stack_t} value are unclear. @Theglibc{} -and most other Unix implementations require the @code{ss_sp} value of -the @code{uc_stack} element to point to the base of the memory region -allocated for the stack and the size of the memory region is stored in -@code{ss_size}. There are implementations out there which require -@code{ss_sp} to be set to the value the stack pointer will have (which -can, depending on the direction the stack grows, be different). This -difference makes the @code{makecontext} function hard to use and it -requires detection of the platform at compile time. - -@comment ucontext.h -@comment SVID -@deftypefun int setcontext (const ucontext_t *@var{ucp}) -@safety{@prelim{}@mtsafe{@mtsrace{:ucp}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} -@c Linux-only implementations mostly in assembly. Some ports use -@c sigreturn or swapcontext syscalls; others restore the signal mask -@c first and then proceed restore other registers in userland, which -@c leaves a window for cancellation or async signals with misaligned or -@c otherwise corrupt stack. ??? Switching to a different stack, or even -@c to an earlier state on the same stack, may conflict with pthread -@c cleanups. This is not quite MT-Unsafe, it's a different kind of -@c safety issue. - -The @code{setcontext} function restores the context described by -@var{ucp}. The context is not modified and can be reused as often as -wanted. - -If the context was created by @code{getcontext} execution resumes with -the registers filled with the same values and the same stack as if the -@code{getcontext} call just returned. - -If the context was modified with a call to @code{makecontext} execution -continues with the function passed to @code{makecontext} which gets the -specified parameters passed. If this function returns execution is -resumed in the context which was referenced by the @code{uc_link} -element of the context structure passed to @code{makecontext} at the -time of the call. If @code{uc_link} was a null pointer the application -terminates normally with an exit status value of @code{EXIT_SUCCESS} -(@pxref{Program Termination}). - -If the context was created by a call to a signal handler or from any -other source then the behaviour of @code{setcontext} is unspecified. - -Since the context contains information about the stack no two threads -should use the same context at the same time. The result in most cases -would be disastrous. - -The @code{setcontext} function does not return unless an error occurred -in which case it returns @code{-1}. -@end deftypefun - -The @code{setcontext} function simply replaces the current context with -the one described by the @var{ucp} parameter. This is often useful but -there are situations where the current context has to be preserved. - -@comment ucontext.h -@comment SVID -@deftypefun int swapcontext (ucontext_t *restrict @var{oucp}, const ucontext_t *restrict @var{ucp}) -@safety{@prelim{}@mtsafe{@mtsrace{:oucp} @mtsrace{:ucp}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} -@c Linux-only implementations mostly in assembly. Some ports call or -@c inline getcontext and/or setcontext, adjusting the saved context in -@c between, so we inherit the potential issues of both. - -The @code{swapcontext} function is similar to @code{setcontext} but -instead of just replacing the current context the latter is first saved -in the object pointed to by @var{oucp} as if this was a call to -@code{getcontext}. The saved context would resume after the call to -@code{swapcontext}. - -Once the current context is saved the context described in @var{ucp} is -installed and execution continues as described in this context. - -If @code{swapcontext} succeeds the function does not return unless the -context @var{oucp} is used without prior modification by -@code{makecontext}. The return value in this case is @code{0}. If the -function fails it returns @code{-1} and sets @var{errno} accordingly. -@end deftypefun - -@heading Example for SVID Context Handling - -The easiest way to use the context handling functions is as a -replacement for @code{setjmp} and @code{longjmp}. The context contains -on most platforms more information which may lead to fewer surprises -but this also means using these functions is more expensive (besides -being less portable). - -@smallexample -int -random_search (int n, int (*fp) (int, ucontext_t *)) -@{ - volatile int cnt = 0; - ucontext_t uc; - - /* @r{Safe current context.} */ - if (getcontext (&uc) < 0) - return -1; - - /* @r{If we have not tried @var{n} times try again.} */ - if (cnt++ < n) - /* @r{Call the function with a new random number} - @r{and the context}. */ - if (fp (rand (), &uc) != 0) - /* @r{We found what we were looking for.} */ - return 1; - - /* @r{Not found.} */ - return 0; -@} -@end smallexample - -Using contexts in such a way enables emulating exception handling. The -search functions passed in the @var{fp} parameter could be very large, -nested, and complex which would make it complicated (or at least would -require a lot of code) to leave the function with an error value which -has to be passed down to the caller. By using the context it is -possible to leave the search function in one step and allow restarting -the search which also has the nice side effect that it can be -significantly faster. - -Something which is harder to implement with @code{setjmp} and -@code{longjmp} is to switch temporarily to a different execution path -and then resume where execution was stopped. - -@smallexample -@include swapcontext.c.texi -@end smallexample - -This an example how the context functions can be used to implement -co-routines or cooperative multi-threading. All that has to be done is -to call every once in a while @code{swapcontext} to continue running a -different context. It is not recommended to do the context switching from -the signal handler directly since leaving the signal handler via -@code{setcontext} if the signal was delivered during code that was not -asynchronous signal safe could lead to problems. Setting a variable in -the signal handler and checking it in the body of the functions which -are executed is a safer approach. Since @code{swapcontext} is saving the -current context it is possible to have multiple different scheduling points -in the code. Execution will always resume where it was left. |