Skip to content

Instantly share code, notes, and snippets.

@hadley hadley/handlers.md
Created May 31, 2018

Embed
What would you like to do?
Walk through of R's condition handler C code

Registering handlers

The key C function that powers both tryCatch() and withCallingHandlers() is do_addCondHands(). It creates handler object with mkHandlerEntry() then stores in the handler stack for the current frame. (More precisely it writes to R_HandlerStack, a global variable that is an alias to c->handlerstack)

The five R arguments to do_addCondHands() are classes, handlers, parentenv, target, and calling. These are combined with a result object (a list of length 4, returned by the exiting handler to doTryCatch()) to create the handler objects which have five components:

  • The class, accessed with ENTRY_CLASS(e). A string given a class name; the handler will match all conditions that contain this component in their class vector.

  • The handler, accessed with ENTRY_HANDLER(e). This is the function called with the condition object. It can also be R_RestartToken, used as part of the restarts system.

  • The parentenv, accessed with ENTRY_CALLING_ENVIR(e). This does not appear to be used.

  • The target environment, accessed with ENTRY_TARGET_ENVIR(e), is only set by tryCatch(). This is used to find the frame that the handler will return to.

  • The calling flag, accessed with IS_CALLING_ENTRY(e) determines if this is a calling/in-place handler (TRUE) or an exiting handler (FALSE).

Signalling conditions

There are four ways for a condition to be signalled:

  • With stop() which calls vsignalError().

  • With an interrupt, which triggers signalInterrupt()

  • With warning(), which calls vsignalWarning(), which then calls vwarningcall_dflt(). (This is particularly complicated because warnings are usually cached and only shown after the top level execution completes.)

  • With signalCondition(), which calls do_signalCondition() (message() calls signalCondition() with a default handler that cat()s the message to stderr().)

Each of C signalling functions works similarly. It finds a matching handler in R_HandlerStack, using findConditionHandler() or similar, and then either calls it or calls gotoExitingHandler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.