Files
mruby-mruby/mrbgems/mruby-error
Yukihiro "Matz" Matsumoto 02fc509555 mruby-error: add comprehensive documentation for C API exception handling functions
Added complete documentation for all C API functions providing exception
handling capabilities in src/exception.c:

## Core C API Functions:

### Exception Protection:
- mrb_protect: executes function under exception protection, equivalent to
  Ruby's begin/rescue blocks, catches exceptions and returns them as objects
  with error state flag for C code exception handling

### Guaranteed Cleanup:
- mrb_ensure: executes function with guaranteed cleanup, equivalent to Ruby's
  begin/ensure blocks, ensures cleanup function always runs regardless of
  exceptions, re-raises caught exceptions after cleanup

### Exception Handling:
- mrb_rescue: executes function with StandardError exception handling,
  convenience wrapper for common rescue patterns, automatically catches
  StandardError and its subclasses

- mrb_rescue_exceptions: executes function with specific exception class
  handling, allows selective exception catching based on class hierarchy,
  re-raises unmatched exceptions for precise error control

## Helper Components:

### Internal Structures:
- protect_data: helper structure to pass function and data to protection
  wrapper, encapsulates function pointer and argument data for safe execution

### Internal Functions:
- protect_body: helper function that wraps user function calls for exception
  protection, extracts function and data from protect_data structure and
  calls user function with proper parameters

Key features documented:
- Exception protection and propagation control
- Guaranteed cleanup execution (ensure semantics)
- Selective exception class handling with inheritance support
- Integration with mruby's exception system and GC
- C API patterns for robust error handling in extensions

Provides complete coverage of exception handling C API for robust error
management in mruby C extensions and embedded applications, essential
for building reliable C code that integrates with mruby's exception system.

Co-authored-by: Atlassian Rovo Dev
2025-08-14 10:52:47 +09:00
..
2016-09-28 12:29:41 +09:00
2025-06-09 17:13:20 +09:00

mruby-error

The mruby-error mrbgem provides a set of C-level APIs for structured exception handling within mruby. These functions allow C extensions or embedded mruby code to implement error handling patterns similar to Ruby's begin, rescue, and ensure keywords. This is particularly useful when writing C code that needs to interact with mruby's exception system in a robust way.

mrb_protect

The mrb_protect function is used to execute a C function (body) and capture any exceptions that might be raised during its execution. This allows you to run potentially unsafe operations and handle errors gracefully.

C Signature:

mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);

Parameters:

  • mrb_state *mrb: The current mruby state.
  • mrb_func_t body: A function pointer to the C function to be executed. This function should have the signature mrb_value (*body)(mrb_state *mrb, mrb_value data).
  • mrb_value data: A mrb_value that will be passed as an argument to the body function.
  • mrb_bool *state: A pointer to a boolean. After mrb_protect returns, this boolean will be:
    • FALSE (0) if the body function executed without raising an exception.
    • TRUE (1) if an exception was raised within the body function.

Return Value:

  • If no exception occurs (*state is FALSE), mrb_protect returns the value returned by the body function.
  • If an exception occurs (*state is TRUE), mrb_protect returns the exception object.

mrb_ensure

The mrb_ensure function ensures that a specific C function (ensure) is executed, regardless of whether another C function (body) completes normally or raises an exception. This is analogous to Ruby's ensure clause.

C Signature:

mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data);

Parameters:

  • mrb_state *mrb: The current mruby state.
  • mrb_func_t body: A function pointer to the main C function to be executed.
  • mrb_value b_data: A mrb_value passed as data to the body function.
  • mrb_func_t ensure: A function pointer to the C function that will always be executed after the body function.
  • mrb_value e_data: A mrb_value passed as data to the ensure function.

Behavior: The body function is executed first. After its completion (either normally or due to an exception), the ensure function is executed. If the body function raised an exception, that exception is re-thrown after the ensure function has finished. The return value of mrb_ensure is the result of the body function if no exception occurred.

mrb_rescue

The mrb_rescue function executes a C function (body) and, if an exception that is a StandardError (or a subclass of StandardError) is raised, it executes a specified rescue C function. This is similar to a rescue clause in Ruby that doesn't specify a particular exception type (which defaults to StandardError).

C Signature:

mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data);

Parameters:

  • mrb_state *mrb: The current mruby state.
  • mrb_func_t body: A function pointer to the main C function to be executed.
  • mrb_value b_data: A mrb_value passed as data to the body function.
  • mrb_func_t rescue: A function pointer to the C function that will be executed if a StandardError (or its subclass) is caught.
  • mrb_value r_data: A mrb_value passed as data to the rescue function.

Behavior: If the body function executes without raising an exception, its result is returned. If a StandardError (or one of its descendants) is raised, the rescue function is executed, and its result becomes the return value of mrb_rescue. If an exception occurs that is not a StandardError (or its subclass), it is not caught by this function and will propagate up the call stack. Similarly, if the rescue block itself raises an exception, that exception will propagate.

mrb_rescue_exceptions

The mrb_rescue_exceptions function provides more fine-grained exception handling than mrb_rescue. It executes a C function (body) and, if an exception matching one of the specified classes is raised, it executes a rescue C function. This is analogous to Ruby's rescue SpecificError1, SpecificError2 => e syntax.

C Signature:

mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data, mrb_int len, struct RClass **classes);

Parameters:

  • mrb_state *mrb: The current mruby state.
  • mrb_func_t body: A function pointer to the main C function to be executed.
  • mrb_value b_data: A mrb_value passed as data to the body function.
  • mrb_func_t rescue: A function pointer to the C function that will be executed if a matching exception is caught.
  • mrb_value r_data: A mrb_value passed as data to the rescue function.
  • mrb_int len: The number of exception classes provided in the classes array.
  • struct RClass **classes: An array of pointers to mruby RClass objects representing the exception classes to be rescued.

Behavior: If the body function executes without raising an exception, its result is returned. If an exception is raised that is an instance of one of the classes specified in the classes array (or a subclass of one of them), the rescue function is executed, and its result becomes the return value of mrb_rescue_exceptions. If an exception occurs that does not match any of the specified classes, it is not caught and will propagate. If the rescue block itself raises an exception, that exception will propagate.

Usage Examples

The C functions provided by this mrbgem are typically used when writing mruby C extensions that need to interact with Ruby code or manage resources carefully in the presence of potential exceptions.

For concrete examples of how these functions are used, please refer to the test files within this mrbgem:

  • test/exception.c: Shows how these C functions are called directly.
  • test/exception.rb: Demonstrates the behavior of these C functions from the Ruby side, through the ExceptionTest module (defined in test/exception.c).

These tests illustrate how to set up callback functions and how the error handling mechanisms behave in practice.