Arguments to Thread#raise?

If I write:

  exc = StandardError.new("foo")
  Thread.main.raise exc, exc.message, exc.backtrace

I get:

  test2.rb:2: foo (StandardError)

But if I write:

  exc = StandardError.new("foo")
  t = Thread.new do
    Thread.main.raise exc, exc.message, exc.backtrace
  end
  t.join

Then I get:

  test2.rb:3:in `raise': wrong number of arguments (3 for 2) (ArgumentError)
          from test2.rb:5:in `join'
          from test2.rb:5

Version:

  ruby 1.9.0 (2004-06-22) [i686-linux]

Is this expected behavior? What are the arguments to Thread#raise
supposed to be?

Paul

  Thread.main.raise exc, exc.message, exc.backtrace

This is Kernel#raise which can take 3 arguments : exception, message,
backtrace

  t = Thread.new do
    Thread.main.raise exc, exc.message, exc.backtrace

This is Thread#raise which can take only 2 arguments : exception and
message

Guy Decoux

> Thread.main.raise exc, exc.message, exc.backtrace

This is Kernel#raise which can take 3 arguments : exception, message,
backtrace

It essentially does the same as Kernel#raise under the hood, but I'm
definitely calling Thread#raise (rb_thread_raise_m), not Kernel#raise
(rb_f_raise).

> t = Thread.new do
> Thread.main.raise exc, exc.message, exc.backtrace

This is Thread#raise which can take only 2 arguments : exception and
message

Why is that (I mean, is there any technical reason for the
inconsistency)?

In order to get the backtrace I wanted, I had to use a pretty ugly
workaround.

Paul

···

On Thu, Jul 08, 2004 at 02:05:42AM +0900, ts wrote:

Hi,

At Thu, 8 Jul 2004 02:53:57 +0900,
Paul Brannan wrote in [ruby-talk:105512]:

>
> > Thread.main.raise exc, exc.message, exc.backtrace
>
> This is Kernel#raise which can take 3 arguments : exception, message,
> backtrace

It essentially does the same as Kernel#raise under the hood, but I'm
definitely calling Thread#raise (rb_thread_raise_m), not Kernel#raise
(rb_f_raise).

The former calls the later if the target thread is current.

> > t = Thread.new do
> > Thread.main.raise exc, exc.message, exc.backtrace
>
> This is Thread#raise which can take only 2 arguments : exception and
> message

Why is that (I mean, is there any technical reason for the
inconsistency)?

I don't know exact reason, but it feels wrong. Also, I suspect
the arguments should be evaluated in the caller's context.

Index: eval.c

···

On Thu, Jul 08, 2004 at 02:05:42AM +0900, ts wrote:

===================================================================
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.675
diff -u -2 -p -r1.675 eval.c
--- eval.c 5 Jul 2004 00:03:11 -0000 1.675
+++ eval.c 7 Jul 2004 22:05:53 -0000
@@ -145,4 +145,6 @@ static VALUE rb_f_block_given_p _((void)
static VALUE umethod_bind _((VALUE, VALUE));
static VALUE rb_mod_define_method _((int, VALUE*, VALUE));
+NORETURN(static void rb_raise_jump _((VALUE)));
+static VALUE rb_make_exception _((int argc, VALUE *argv));

static int scope_vmode;
@@ -4391,4 +4393,13 @@ rb_f_raise(argc, argv)
     VALUE *argv;
{
+ rb_raise_jump(rb_make_exception(argc, argv));
+ return Qnil; /* not reached */
+}
+
+static VALUE
+rb_make_exception(argc, argv)
+ int argc;
+ VALUE *argv;
+{
     VALUE mesg;
     ID exception;
@@ -4430,4 +4441,11 @@ rb_f_raise(argc, argv)
     }

+ return mesg;
+}
+
+static void
+rb_raise_jump(mesg)
+ VALUE mesg;
+{
     if (ruby_frame != top_frame) {
   PUSH_FRAME(); /* fake frame */
@@ -4437,6 +4455,4 @@ rb_f_raise(argc, argv)
     }
     rb_longjmp(TAG_RAISE, mesg);
-
- return Qnil; /* not reached */
}

@@ -9765,6 +9781,5 @@ rb_thread_check(data)
static VALUE rb_thread_raise _((int, VALUE*, rb_thread_t));

-static int th_raise_argc;
-static VALUE th_raise_argv[2];
+static VALUE th_raise_exception;
static NODE *th_raise_node;
static VALUE th_cmd;
@@ -9866,5 +9881,5 @@ rb_thread_switch(n)
   ruby_frame->last_func = 0;
   ruby_current_node = th_raise_node;
- rb_f_raise(th_raise_argc, th_raise_argv);
+ rb_raise_jump(th_raise_exception);
   break;
       case RESTORE_SIGNAL:
@@ -9872,5 +9887,5 @@ rb_thread_switch(n)
   break;
       case RESTORE_EXIT:
- ruby_errinfo = th_raise_argv[0];
+ ruby_errinfo = th_raise_exception;
   ruby_current_node = th_raise_node;
   error_print();
@@ -10035,6 +10050,5 @@ rb_thread_main_jump(err, tag)
{
     curr_thread = main_thread;
- th_raise_argc = 1;
- th_raise_argv[0] = err;
+ th_raise_exception = err;
     th_raise_node = ruby_current_node;
     rb_thread_restore_context(main_thread, tag);
@@ -11817,4 +11831,5 @@ rb_thread_raise(argc, argv, th)
{
     volatile rb_thread_t th_save = th;
+ VALUE exc;

     if (!th->next) {
@@ -11822,6 +11837,7 @@ rb_thread_raise(argc, argv, th)
     }
     if (rb_thread_dead(th)) return Qnil;
+ exc = rb_make_exception(argc, argv);
     if (curr_thread == th) {
- rb_f_raise(argc, argv);
+ rb_raise_jump(exc);
     }

@@ -11832,9 +11848,8 @@ rb_thread_raise(argc, argv, th)
     }

- rb_scan_args(argc, argv, "11", &th_raise_argv[0], &th_raise_argv[1]);
     rb_thread_ready(th);
     curr_thread = th;

- th_raise_argc = argc;
+ th_raise_exception = exc;
     th_raise_node = ruby_current_node;
     rb_thread_restore_context(curr_thread, RESTORE_RAISE);

--
Nobu Nakada

The code is much easier to read/follow this way, too.

Paul

···

On Thu, Jul 08, 2004 at 07:17:12AM +0900, nobu.nokada@softhome.net wrote:

I don't know exact reason, but it feels wrong. Also, I suspect
the arguments should be evaluated in the caller's context.

Hi,

···

In message "Re: arguments to Thread#raise ?" on 04/07/08, nobu.nokada@softhome.net <nobu.nokada@softhome.net> writes:

I don't know exact reason, but it feels wrong. Also, I suspect
the arguments should be evaluated in the caller's context.

I like this. Commit to the HEAD. Do you think it's good enough for
last minute change to 1.8.2? If you feel so, go ahead and commit.

              matz.