Commit Graph

61 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 07470eb538 mruby-exit.c: make exit() to raise SystemExit exception.
Now it allows error handlers to work, unlike `exit!`.
2022-09-21 22:37:23 +09:00
Yukihiro "Matz" Matsumoto 4669d43f50 error.h: move rbreak_tag definitions to src/vm.c. 2022-09-05 07:30:12 +09:00
Yukihiro "Matz" Matsumoto 06c4c76be8 Merge branch 'exception' of https://github.com/dearblue/mruby into dearblue-exception 2022-05-01 20:00:37 +09:00
dearblue ef5ae084d7 Must the mrb_sys_fail() function raise an exception
Normal return of control from the `mrb_sys_fail()` function has unexpected results.
Example: double free, malloc with huge size used as error integer

The following is an example of an actual crash:

```console
% cat crash.rb
def SystemCallError._sys_fail(*a)
  nil
end

File.readlink("/404")

% bin/mruby crash.rb
zsh: segmentation fault (core dumped)  bin/mruby crash.rb
```
2022-04-10 21:36:59 +09:00
Yukihiro "Matz" Matsumoto b99c389ec3 internal.h: aggregate internal functions.
Internal functions can only be called from within the library.
Functions listed in `mruby/internal.h` can be called from:

* core (src/*.c)
* gems (mrbgems/**/*.c)

But not from the application linked with `libmruby`.
2022-04-02 18:25:13 +09:00
dearblue 92ef9f1a9e Store backtrace to field of struct RException
Since the possible values of the backtrace are limited to `nil`, `RData`, and `RAray`, they are now stored as object pointers.

This change saves memory by eliminating the need to use instance variables for common exceptions.

ref. #2485
2022-04-01 23:27:19 +09:00
dearblue 7d85092bc4 Reorganize the struct RException::mesg member
There is no need to limit the type to `struct RString`.
Also, the `MRB_EXC_MESG_STRING_FLAG` flag can be eliminated by checking if `struct RException::mesg` is `NULL` or not.

ref. #2485
2022-04-01 23:25:20 +09:00
Yukihiro "Matz" Matsumoto b6531fa691 error.h: remove obsolete macro mrb_exc_new_str_lit(). 2022-03-03 14:48:39 +09:00
dearblue d6773cbd71 Avoid direct access to error messages as instance variables
ref. #2485

The `SystemCallError#to_s` method also needed to be modified, but since it has no functional difference from the `Exception#to_s` method, it will be removed.
2022-02-06 15:45:13 +09:00
Yukihiro "Matz" Matsumoto 291234c7aa Merge branch 'exc_mesg' of https://github.com/take-cheeze/mruby into take-cheeze-exc_mesg 2021-10-12 22:14:11 +09:00
Yukihiro "Matz" Matsumoto 1a82bab1b0 error.h: rename mrb_protect_raw to mrb_protect_error; #5415
- `_raw` does not describe the nature of the function
- the function protect errors during C function execution
2021-04-22 17:01:33 +09:00
Yukihiro "Matz" Matsumoto ff366b65eb Merge pull request #5415 from dearblue/unwind-mrb_protect
Introducing the `mrb_protect_raw()` API function
2021-04-19 22:34:20 +09:00
dearblue 891e852286 Introducing the mrb_protect_raw() API function
The purpose is two-fold:

 1. to be able to specify a pointer directly when user data is used

    When using `mrb_protect()`, it is necessary to allocate objects by `mrb_obj_cptr()` function when using user data.

    Adding `mrb_protect_raw()` will make it simpler to reimplement `mrbgems/mruby-error`.

 2. to correctly unwind callinfo when an exception is raised from a C function defined as a method (the main topic)

    If a method call is made directly under `mrb_protect()` and a C function is called, control is returned from `mrb_protect()` if an exception occurs there.
    In this case, callinfo is not restored, so it is out of sync.
    Moreover, returning to mruby VM (`mrb_vm_exec()` function) in this state will indicate `ci->pc` of C function which is equal to `NULL`, and subsequent `JUMP` will cause `SIGSEGV`.

    Following is an example that actually causes `SIGSEGV`:

    - `crash.c`

      ```c
      #include <mruby.h>
      #include <mruby/compile.h>
      #include <mruby/error.h>

      static mrb_value
      level1_body(mrb_state *mrb, mrb_value self)
      {
        return mrb_funcall(mrb, self, "level2", 0);
      }

      static mrb_value
      level1(mrb_state *mrb, mrb_value self)
      {
        return mrb_protect(mrb, level1_body, self, NULL);
      }

      static mrb_value
      level2(mrb_state *mrb, mrb_value self)
      {
        mrb_raise(mrb, E_RUNTIME_ERROR, "error!");
        return mrb_nil_value();
      }

      int
      main(int argc, char *argv[])
      {
        mrb_state *mrb = mrb_open();
        mrb_define_method(mrb, mrb->object_class, "level1", level1, MRB_ARGS_NONE());
        mrb_define_method(mrb, mrb->object_class, "level2", level2, MRB_ARGS_NONE());
        mrb_p(mrb, mrb_load_string(mrb, "p level1"));
        mrb_close(mrb);
        return 0;
      }
      ```

    - compile & run

      ```console
      % `bin/mruby-config --cc --cflags --ldflags` crash.c `bin/mruby-config --libs`

      % ./a.out
      zsh: segmentation fault (core dumped)  ./a.out
      ```

    After applying this patch, it will print exception object and exit normally.

The `mrb_protect()`, `mrb_ensure()` and `mrb_rescue_exceptions()` in `mrbgems/mruby-error` have been rewritten using `mrb_protect_raw()`.
2021-04-19 22:11:57 +09:00
Yukihiro "Matz" Matsumoto 9d362f2c27 backtrace.c: remove MRB_API from internal functions.
- `mrb_exc_backtrace` to implement `Exception#backtrace`
- `mrb_get_backtrace` to implement `#caller`
2021-04-19 15:49:51 +09:00
Sutou Kouhei a00eabbf5d Fix typo in backward compatible mrb_exc_new_str_lit() macro 2020-11-10 16:03:05 +09:00
Yukihiro "Matz" Matsumoto 7e3d22f095 Raname mrb_exc_new_str_lit() to mrb_exc_new_lit().
It uses `mrb_str_new_lit()` internally, but it doesn't need to express
it in the name of the function (macro).
2020-10-12 18:20:06 +09:00
Yukihiro "Matz" Matsumoto 8a87549315 Rename float configuration option names.
- `MRB_WITHOUT_FLOAT` => `MRB_NO_FLOAT`
- `MRB_USE_FLOAT` => `MRB_USE_FLOAT32`

The former is to use `USE_XXX` naming convention. The latter is to make
sure `float` is 32bit float and not floating point number in general.
2020-10-12 16:21:40 +09:00
dearblue c1f112c49a Replace global jump with catch handler implementation
When a global jump occurs, look at the catch handler table to determine where to jump.
In that case, `pc` already shows the following instruction, but since the table shows `begin_offset ... end_offset`, the comparison is done with `begin_offset < pc && pc <= end_offset`.
If there is a corresponding handler, move `pc` to `handler.target_offset` and continue running the VM.

When a global jump across `ensure` is made by `return`, `break`, `next`, `redo` and `retry`, the extended `RBreak` object saves and restores the C-level execution position.
This extended `RBreak` can have tag information, which makes it a pseudo coroutine (the "tag" mimics CRuby).

The implementation of pseudo coroutines by `RBreak` is summarized by `CHECKPOINT_RESTORE ... CHECKPOINT_MAIN ... CHECKPOINT_END` and `throw_tagged_break` / `unwind_ensure` macros.
The restart of processing is branched by `RBREAK_TAG_FOREACH(DISPATCH_CHECKPOINTS)`.

- Not only `rescue` blocks but also `ensure` blocks are now sandwiched between `OP_EXCEPT` and `OP_RAISEIF`.

- Remove the function `ecall()`.
  It is no longer necessary to re-enter the VM to perform an "ensure block".

  This will resolves #1888.

- Added instruction `OP_JUW` (Jump while UnWind).

  It jumps unconditionally like `OP_JMP`, but searches the catch handler table and executes the ensure block.
  Since it searches the catch handler table, it is much heavier than `OP_JMP`.
2020-10-12 16:21:33 +09:00
Yukihiro "Matz" Matsumoto 52507b1083 Generate C struct from irep instead of binary dump. 2020-10-12 16:21:10 +09:00
Yukihiro "Matz" Matsumoto fa85f91e0e Add type cast to avoid an error from int and enum mixture; fix #4786 2019-10-23 14:47:55 +09:00
Yukihiro "Matz" Matsumoto 5cd52d2d69 Fix an error in refactoring; fix #4682 2019-09-02 08:41:44 +09:00
Yukihiro "Matz" Matsumoto d48a2190bf Refactor #4662 with different names. 2019-08-31 22:14:25 +09:00
David Siaw 6375639917 fix lots of warnings and make logo not so big 2019-08-26 02:08:33 +09:00
KOBAYASHI Shuji be78b5d8f7 Fix RBreak exceeding 6 words on 32-bit mode w/o boxing and MRB_USE_FLOAT
ref: https://github.com/mruby/mruby/pull/4483#issuecomment-498001736

In this configuration, `tt` of `RBreak::val` is set into `RBreak::flags`.
2019-08-23 22:15:42 +09:00
David Siaw b5299b1c58 fix up documentation for values 2019-08-18 20:12:44 +09:00
Yukihiro "Matz" Matsumoto c2660b8111 Fix missing MRB_API prefix for functions below; clse #4267
Functions to add prototypes to headers:
* mrb_ary_splice()
* mrb_notimplement()
* mrb_vformat()
* mrb_cstr_to_dbl()
* mrb_cstr_to_inum()

Functions to be made `static` (`MRB_API` was not needed):
* mrb_mod_module_function()
* mrb_obj_hash()
* mrb_str_len_to_inum()

Functions to remove `MRB_API` from definitions (referenced from within `libmruby`):
* mrb_mod_cv_defined()
* mrb_mod_cv_get()
* mrb_f_send()
2019-03-26 10:23:52 +09:00
Yukihiro "Matz" Matsumoto 8b7a8978e2 Reduce the size of struct RBreak to reduce memory usage.
The old size of `struct RBreak` was 56 bytes (`MRB_NO_BOXING`)
and it's bigger than other object structures. That increase the
size of `RVALUE` thus increase the total amount of memory consumption.
2017-11-20 18:33:41 +09:00
Tomasz Dąbrowski 971a4f9122 fix: src\kernel.c(874): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Yukihiro "Matz" Matsumoto d4d99dd6d7 Allow break from a block called by mrb_yield; close #3359
This means #3701 is now OK to merge.
2017-06-16 11:34:11 +09:00
Yukihiro "Matz" Matsumoto ff7df939ba Restore MRB_API function mrb_exc_backtrace(mrb, exc); ref 9644ad5 2017-05-31 23:15:17 +09:00
Yukihiro "Matz" Matsumoto 9644ad51b4 Simplify backtrace mechanism; fix #3633 #3634 #3644
Instead of preserving a backtrace in `mrb_state`, `mrb_exc_set`
keeps packed backtrace in an exception object. `#backtrace` unpacks
it to an array of strings.
2017-05-23 23:50:42 +09:00
Yukihiro "Matz" Matsumoto 065966dae4 common.h are supposed to be included from other header, so call it with quotes; ref #3032 2015-11-28 00:10:38 +09:00
Yukihiro "Matz" Matsumoto 5c405dea3d include changed from by quotes ("") to by brackets (<>); close #3032 2015-11-27 17:48:23 +09:00
Seba Gamboa d4238494eb Tag include/mruby/error.h functions with required mrbgem tag 2015-10-21 17:03:43 -03:00
Seba Gamboa 25c8e95365 Revert "Mark core gems with mrbgem tag"
This reverts commit 5cdcce8dbd.
2015-10-21 14:31:13 -03:00
Seba Gamboa 5cdcce8dbd Mark core gems with mrbgem tag 2015-10-20 12:16:47 -03:00
Seba Gamboa a0fe0c40b1 Remove old doxygen tags 2015-10-08 12:29:10 -03:00
Seba Gamboa 40bf7bde78 Sorting documentation grouping 2015-09-21 01:48:42 -03:00
Seba Gamboa c127614638 Setting up doxygen groups 2015-09-20 21:14:07 -03:00
Yukihiro "Matz" Matsumoto 1085167fef add an small comment description in mruby/error.h header 2015-07-15 14:47:15 +09:00
take_cheeze f6b5a82972 Use class array instead of variadic. 2015-07-15 14:47:15 +09:00
take_cheeze cdd72d9c37 Implement mrb_protect, mrb_ensure, mrb_rescue, mrb_rescue_exceptions.
(`mrb_rescue_exceptions` is mruby implementation of `rb_rescue2`.)
Closes #2844, closes #2837.
2015-07-15 14:46:56 +09:00
Yukihiro "Matz" Matsumoto 9c311ddc93 refactor mrb_bob_missing to share raising NoMethodError code; fix #2878
Note: arguments of mrb_no_method_error() has changed. You need to replace
3rd and 4th argument (say n, argv) to mrb_ary_new_from_values(mrb, n, argv).
2015-07-13 11:07:59 +09:00
Yukihiro "Matz" Matsumoto c5a23e6a0d remove header prototype of mrb_exc_print; close #2607 2014-10-15 21:21:58 +09:00
Kouhei Sutou 55dca8337e Remove duplicated mrb_print_backtrace() declaration
It is declared in mruby.h.
2014-09-27 23:53:25 +09:00
Tatsuhiko Kubo 3b904e9408 Unify include guard styles and header comments. 2014-08-21 13:27:37 +09:00
Yukihiro "Matz" Matsumoto 206f89e209 add MRB_API modifiers to mruby API functions 2014-08-04 00:47:08 +09:00
take_cheeze f77fb11f4e Use RString in mesg instead. 2014-07-28 20:30:02 +09:00
take_cheeze e926b532ee Store exception message to mesg field of struct RException. 2014-07-28 16:34:01 +09:00
take_cheeze 3c96602574 Use MRB_TT_EXCEPTION in exception object. 2014-07-21 23:09:13 +09:00