I believe that, in Ruby 1.8, Continuation.call raises

RuntimeError.new "continuation called across trap"

in situations that should be allowed.

The error occurs when the current cont_protect context is different from
the one that was stored in the continuation object when it was created
(with callcc).

cont_protect is assigned a new unique value whenever a trap is executed.
The original intent seems to have been to ensure that a continuation
created in one trap context (or in the main context) did not get called
on
another.  This certainly makes sense, as I could see where Unix signal
handling would be corrupted if the stack were replaced while processing
a different trap.

However...

cont_protect is also assigned a new unique value whenever as string is
evaluated.  It is also assigned by rb_protect(), which is exported from
eval.c and used by extensions to handle exceptions raised by ruby code.

As a consequence, for instance, one cannot call an continuation created
(with callcc) while evaluating a string in any other eval string.

The error message in these cases is incorrect, for the problem has
nothing to do with traps of any kind.

Further, I cannot see why an exception is raised at all.

As an experiment, I modified rb_protect() as follows:

VALUE
rb_protect(proc, data, state)
    VALUE (*proc) _((VALUE));
    VALUE data;
    int * volatile state;
{
    VALUE result = Qnil;
    int status;

    PUSH_TAG(PROT_NONE);
    if ((status = EXEC_TAG()) == 0) {
  result = (*proc)(data);
    }
    POP_TAG();
    if (state) {
  *state = status;
    }
    return result;
}

And I renamed the original rb_protect() to rb_trap_protect() and
gave it "static" linkage.  I then modified rb_trap_eval to call
rb_trap_protect() instead of rb_protect().

With this change cont_protect is *only* modified when a trap is
evaluated.

This suppressed the bogus exceptions that had been raised by
Continuation#call and "fixes" my application.

Note, that I'm not the first person to complain about this.
See:
  http://www.ruby-forum.com/topic/82927

The self contained test case presented in topic 82927 deals with
continuations across forks, but the issue is related and both are
corrected by the change I proposed above.

Is there really some reason that Continuation.call should be this
restrictive?

If we agree there is none, would you like me to submit this as a
(trivial) patch?  It clearly makes the common case of rb_protect()
faster and leaves the eval_trap case unchanged.

- brent

-- 
Posted via http://www.ruby-forum.com/.