123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- @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
- @deftp {Data Type} jmp_buf
- @standards{ISO, setjmp.h}
- 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
- @deftypefn Macro int setjmp (jmp_buf @var{state})
- @standards{ISO, setjmp.h}
- @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
- @deftypefun void longjmp (jmp_buf @var{state}, int @var{value})
- @standards{ISO, setjmp.h}
- @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
- @deftp {Data Type} sigjmp_buf
- @standards{POSIX.1, setjmp.h}
- This is similar to @code{jmp_buf}, except that it can also store state
- information about the set of blocked signals.
- @end deftp
- @deftypefun int sigsetjmp (sigjmp_buf @var{state}, int @var{savesigs})
- @standards{POSIX.1, setjmp.h}
- @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
- @deftypefun void siglongjmp (sigjmp_buf @var{state}, int @var{value})
- @standards{POSIX.1, setjmp.h}
- @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.
- @deftp {Data Type} ucontext_t
- @standards{SVID, ucontext.h}
- 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:
- @deftypefun int getcontext (ucontext_t *@var{ucp})
- @standards{SVID, ucontext.h}
- @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.
- @strong{Compatibility Note:} Depending on the operating system,
- information about the current context's stack may be in the
- @code{uc_stack} field of @var{ucp}, or it may instead be in
- architecture-specific subfields of the @code{uc_mcontext} field.
- The function returns @code{0} if successful. Otherwise it returns
- @code{-1} and sets @code{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.
- @deftypefun void makecontext (ucontext_t *@var{ucp}, void (*@var{func}) (void), int @var{argc}, @dots{})
- @standards{SVID, ucontext.h}
- @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.
- @deftypefun int setcontext (const ucontext_t *@var{ucp})
- @standards{SVID, ucontext.h}
- @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.
- @deftypefun int swapcontext (ucontext_t *restrict @var{oucp}, const ucontext_t *restrict @var{ucp})
- @standards{SVID, ucontext.h}
- @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 @code{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.
|