Hi all,

Please disregard my previous email- the (potential) bug is now submitted 
as an issue on github for mruby.

Cheers,
Garth

On 26/02/13 17:59, Garthy D wrote:
>
> Hi all,
>
> Originally posted to ruby-talk, in case it was a mistake on my end. It
> was suggested I post the message to ruby-core:
>
> I have been having a bit of a play around with mruby (note: mruby, not
> MRI Ruby), and I believe I may have found a bug in a recent (20130222)
> version.
>
> Basically, if you call mrb_load_string with something that returns a
> class, then make a call on the returned object that throws an exception,
> and then call mrb_load_string with a string that makes the same kind of
> return, the class in question has somehow vanished from the environment,
> and the second load will fail.
>
> Test program and Makefile below. The test string is simply "Float",
> which returns the Float class. The first time it calls it, it is okay.
> The second time, "Float" no longer exists.
>
> Naturally, if you remove the call to 'dummyCall', the second load works
> as it should.
>
> I have seen the problem with other classes as well, although the
> specifics of what triggers the problem can vary. It is hard to make a
> general statement as to the exact fault. As a general rule, if any Class
> is returned from mrb_load_string, and a subsequent call on the return
> generates an exception, depending on what you do, the whole Class may or
> may not (seem to) be removed from the current environment.
>
> I can't guarantee my code below is bug-free- I'm still fairly new to
> mruby. It is possible I have made an incorrect assumption in the code
> below. If not, it looks like a mruby bug.
>
> I am using mruby as checked out on 20130222 (22/2/13), Linux, Debian,
> 64-bit. Can supply additional information if needed.
>
> Cheers,
> Garth
>
> -----------------
> floatnom.c
> -----------------
>
> #include <mruby.h>
> #include <mruby/compile.h>
> #include <mruby/string.h>
> #include <assert.h>
> #include <string.h>
>
> static void show_result(mrb_state *mrb, mrb_value v)
> {
> switch (mrb_type(v))
> {
> case MRB_TT_CLASS:
> fprintf(stderr, "- Type Class returned.\n");
> break;
> case MRB_TT_FALSE:
> fprintf(stderr, "- Type false/nil returned.\n");
> break;
> default:
> fprintf(stderr, "- Type %d returned.\n", mrb_type(v));
> break;
> }
>
> if (mrb->exc)
> {
> struct RObject *exc = mrb->exc;
> mrb->exc = 0;
> mrb_value e = mrb_obj_value(exc);
> mrb_value e_to_s = mrb_funcall(mrb, e, "to_s", 0);
> assert(mrb->exc == 0);
> if (mrb_type(e_to_s) == MRB_TT_STRING)
> {
> char buff[512];
> memcpy(buff, RSTRING_PTR(e_to_s), RSTRING_LEN(e_to_s));
> buff[RSTRING_LEN(e_to_s)] = '\0';
> fprintf(stderr, "- Exception was: %s\n", buff);
> }
> else
> fprintf(stderr, "- Exception could not be identified.\n");
> assert(mrb->exc == 0);
> }
> else
> fprintf(stderr, "- No exception.\n");
> }
>
> int main(int argc, char *argv[])
> {
> mrb_state *mrb = mrb_open();
>
> fprintf(stderr, "Loading first string:\n");
> mrb_value v1 = mrb_load_string(mrb, "Float");
> show_result(mrb, v1);
>
> fprintf(stderr, "Making bad call:\n");
> mrb_value v2 = mrb_funcall(mrb, v1, "dummyCall", 0);
> show_result(mrb, v2);
>
> fprintf(stderr, "Loading same string again. Should work, but doesn't.\n");
> mrb_value v3 = mrb_load_string(mrb, "Float");
> show_result(mrb, v3);
>
> mrb_close(mrb);
> return 0;
> }
>
> -----------------
> Makefile
> -----------------
>
> floatnom: floatnom.o
> gcc -o floatnom floatnom.o -L/path/to/mruby/lib -lmruby -lm
>
> floatnom.o: floatnom.c
> gcc -Wall -o floatnom.o -I/path/to/mruby/include -c floatnom.c
>
> clean:
> rm -f floatnom floatnom.o
>
>
> -----------------
> Typical output
> -----------------
>
> (May be typos- transcribed by hand)
>
> Loading first string:
> - Type Class returned.
> - No exception.
> Making bad call:
> - Type false/nil returned.
> - Exception was: undefined method 'dummyCall' for Float
> Loading same string again. Should work, but doesn't.
> - Type false/nil returned.
> - Exception was: uninitialized constant Float
>
>
>
>
>