mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			451 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			451 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| @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})
 | |
| 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})
 | |
| 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 a 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})
 | |
| 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})
 | |
| 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 function were part of the
 | |
| original @w{System V} API and by this route were added to the Unix
 | |
| API.  Beside 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 as 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})
 | |
| 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 the function returns for the first
 | |
| time or whether the initialized context was used and the execution is
 | |
| resumed at just that point.  If this is necessary the user has to take
 | |
| 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.  The latter is normally done to implement co-routines or
 | |
| similar constructs.  The @code{makecontext} function is what has to be
 | |
| used to do that.
 | |
| 
 | |
| @comment ucontext.h
 | |
| @comment SVID
 | |
| @deftypefun void makecontext (ucontext_t *@var{ucp}, void (*@var{func}) (void), int @var{argc}, @dots{})
 | |
| 
 | |
| The @var{ucp} parameter passed to the @code{makecontext} shall be
 | |
| initialized by a call to @code{getcontext}.  The context will be
 | |
| modified to in a way so 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 is 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 threads stack or explicitly allocate 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 implements 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})
 | |
| 
 | |
| 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}).
 | |
| 
 | |
| 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})
 | |
| 
 | |
| 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 set @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 might lead to less surprises
 | |
| but this also means using these functions is more expensive (beside
 | |
| 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 allowed to do the context switching from
 | |
| the signal handler directly since neither @code{setcontext} nor
 | |
| @code{swapcontext} are functions which can be called from a signal
 | |
| handler.  But setting a variable in the signal handler and checking it
 | |
| in the body of the functions which are executed.  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.
 |