summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--eval.c60
-rw-r--r--lib/debug.rb99
-rw-r--r--lib/timeout.rb8
4 files changed, 104 insertions, 68 deletions
diff --git a/ChangeLog b/ChangeLog
index 3e34db44fe..265f85a164 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sat Oct 14 03:32:13 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_alloc): should not link a new thread in the
+ live thread ring before initialization.
+
Fri Oct 13 17:08:09 2000 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb: new file.
diff --git a/eval.c b/eval.c
index 5b6dd3cbb6..b56b8bd768 100644
--- a/eval.c
+++ b/eval.c
@@ -664,7 +664,6 @@ dvar_asgn_internal(id, value, curr)
struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
- if (TYPE(vars) != T_VARMAP) abort();
if (curr && vars->id == 0) {
n++;
if (n == 2) break;
@@ -729,6 +728,7 @@ struct tag {
struct SCOPE *scope;
int dst;
struct tag *prev;
+ int line;
};
static struct tag *prot_tag;
@@ -742,6 +742,7 @@ static struct tag *prot_tag;
_tag.scope = ruby_scope; \
_tag.tag = ptag; \
_tag.dst = 0; \
+ _tag.line = __LINE__; \
prot_tag = &_tag;
#define PROT_NONE 0
@@ -798,6 +799,7 @@ static VALUE ruby_wrapper; /* security wrapper */
typedef struct thread * rb_thread_t;
static rb_thread_t curr_thread = 0;
+static rb_thread_t main_thread;
static void scope_dup _((struct SCOPE *));
#define POP_SCOPE() \
@@ -868,8 +870,8 @@ set_backtrace(info, bt)
static void
error_print()
{
- VALUE errat = Qnil;
- VALUE eclass;
+ VALUE errat = Qnil; /* OK */
+ volatile VALUE eclass;
char *einfo;
int elen;
@@ -3274,9 +3276,10 @@ rb_longjmp(tag, mesg)
if (RTEST(ruby_debug) && !NIL_P(ruby_errinfo)
&& !rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
- fprintf(stderr, "Exception `%s' at %s:%d\n",
+ fprintf(stderr, "Exception `%s' at %s:%d - %s\n",
rb_class2name(CLASS_OF(ruby_errinfo)),
- ruby_sourcefile, ruby_sourceline);
+ ruby_sourcefile, ruby_sourceline,
+ STR2CSTR(ruby_errinfo));
}
rb_trap_restore_mask();
@@ -4837,7 +4840,7 @@ yield_under_i(self)
POP_TAG();
ruby_block = old_block;
if (state) JUMP_TAG(state);
-
+
return result;
}
/* static block, no need to restore */
@@ -4930,7 +4933,7 @@ rb_load(fname, wrap)
char *file;
volatile ID last_func;
volatile VALUE wrapper = 0;
- VALUE self = ruby_top_self;
+ volatile VALUE self = ruby_top_self;
TMP_PROTECT;
if (wrap) {
@@ -6146,7 +6149,7 @@ block_pass(self, node)
VALUE self;
NODE *node;
{
- VALUE block = rb_eval(self, node->nd_body);
+ VALUE block = rb_eval(self, node->nd_body); /* OK */
struct BLOCK * volatile old_block;
struct BLOCK _block;
struct BLOCK *data;
@@ -6623,9 +6626,6 @@ struct thread {
#define THREAD_RAISED 0x200
-static rb_thread_t main_thread;
-/*static rb_thread_t curr_thread = 0;*/
-
#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
#define END_FOREACH_FROM(f,x) } while (x != f)
@@ -6754,7 +6754,6 @@ rb_thread_save_context(th)
rb_thread_t th;
{
VALUE *pos;
-
int len;
len = stack_length(&pos);
@@ -7005,7 +7004,6 @@ find_bad_fds(dst, src, max)
fd_set *dst, *src;
int max;
{
- struct stat s;
int i, test = Qfalse;
for (i=0; i<=max; i++) {
@@ -7300,7 +7298,6 @@ rb_thread_select(max, read, write, except, timeout)
struct timeval *timeout;
{
double limit;
- struct timeval zero;
int n;
if (!read && !write && !except) {
@@ -7643,6 +7640,9 @@ rb_thread_abort_exc_set(thread, val)
#define THREAD_ALLOC(th) do {\
th = ALLOC(struct thread);\
\
+ th->next = 0;\
+ th->prev = 0;\
+\
th->status = THREAD_RUNNABLE;\
th->result = 0;\
th->errinfo = Qnil;\
@@ -7696,7 +7696,6 @@ rb_thread_alloc(klass)
}
else {
curr_thread = th->prev = th->next = th;
- th->status = THREAD_RUNNABLE;
}
for (vars = th->dyna_vars; vars; vars = vars->next) {
@@ -7758,11 +7757,12 @@ rb_thread_stop_timer()
#endif
static VALUE
-rb_thread_start_0(fn, arg, th)
+rb_thread_start_0(fn, arg, th_arg)
VALUE (*fn)();
void *arg;
- rb_thread_t th;
+ rb_thread_t th_arg;
{
+ volatile rb_thread_t th = th_arg;
volatile VALUE thread = th->thread;
enum thread_status status;
int state;
@@ -7791,7 +7791,7 @@ rb_thread_start_0(fn, arg, th)
PUSH_TAG(PROT_THREAD);
if ((state = EXEC_TAG()) == 0) {
- if (THREAD_SAVE_CONTEXT(th) == 0) {
+ if ((status = THREAD_SAVE_CONTEXT(th)) == 0) {
curr_thread = th;
th->result = (*fn)(arg, th);
}
@@ -7833,7 +7833,8 @@ rb_thread_create(fn, arg)
VALUE (*fn)();
void *arg;
{
- return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
+ rb_thread_t th = rb_thread_alloc(rb_cThread);
+ return rb_thread_start_0(fn, arg, th);
}
int
@@ -7864,7 +7865,7 @@ rb_thread_s_new(argc, argv, klass)
pos = th->stk_pos;
rb_obj_call_init(th->thread, argc, argv);
if (th->stk_pos == pos) {
- rb_raise(rb_eThreadError, "uninitialized thread - check `initialize' of %s",
+ rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
rb_class2name(klass));
}
@@ -7875,20 +7876,27 @@ static VALUE
rb_thread_initialize(thread, args)
VALUE thread, args;
{
+ rb_thread_t th;
+
+ th = rb_thread_check(thread);
if (!rb_block_given_p()) {
+ rb_thread_remove(th);
rb_raise(rb_eThreadError, "must be called with a block");
}
- return rb_thread_start_0(rb_thread_yield, args, rb_thread_check(thread));
+ return rb_thread_start_0(rb_thread_yield, args, th);
}
static VALUE
rb_thread_start(klass, args)
VALUE klass, args;
{
+ rb_thread_t th;
+ VALUE t;
+
if (!rb_block_given_p()) {
rb_raise(rb_eThreadError, "must be called with a block");
}
- return rb_thread_start_0(rb_thread_yield, args, rb_thread_alloc(klass));
+ return rb_thread_start_0(rb_thread_yield, args, rb_thread_alloc(rb_cThread));
}
static VALUE
@@ -8092,6 +8100,7 @@ rb_thread_raise_m(argc, argv, thread)
rb_secure(4);
}
rb_thread_raise(argc, argv, th);
+ return Qnil; /* not reached */
}
VALUE
@@ -8170,7 +8179,7 @@ rb_thread_inspect(thread)
{
char *cname = rb_class2name(CLASS_OF(thread));
rb_thread_t th = rb_thread_check(thread);
- char *s, *status;
+ char *status;
VALUE str;
switch (th->status) {
@@ -8205,8 +8214,8 @@ rb_callcc(self)
struct RVarmap *vars;
THREAD_ALLOC(th);
- cont = Data_Wrap_Struct(rb_cCont, thread_mark,
- thread_free, th);
+ th->status = THREAD_RUNNABLE;
+ cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
scope_dup(ruby_scope);
for (tag=prot_tag; tag; tag=tag->prev) {
@@ -8478,4 +8487,3 @@ return_check()
tt = tt->prev;
}
}
-
diff --git a/lib/debug.rb b/lib/debug.rb
index 97be752797..04e6c730c7 100644
--- a/lib/debug.rb
+++ b/lib/debug.rb
@@ -5,15 +5,16 @@ if $SAFE > 0
STDERR.print "-r debug.rb is not available in safe mode\n"
exit 1
end
-SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
require 'tracer'
+
class Tracer
def Tracer.trace_func(*vars)
Single.trace_func(*vars)
end
end
+SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
class DEBUGGER__
class Mutex
@@ -89,6 +90,7 @@ class DEBUGGER__
@frames = []
@finish_pos = 0
@trace = false
+ @catch = "StandardError"
end
def stop_next(n=1)
@@ -130,16 +132,8 @@ class DEBUGGER__
def var_list(ary, binding)
ary.sort!
- if false # ary.size < 0
- f = open("|less", "w")
- for v in ary
- f.printf " %s => %s\n", v, eval(v, binding).inspect
- end
- f.close
- else
- for v in ary
- stdout.printf " %s => %s\n", v, eval(v, binding).inspect
- end
+ for v in ary
+ stdout.printf " %s => %s\n", v, eval(v, binding).inspect
end
end
@@ -158,7 +152,7 @@ class DEBUGGER__
when /^\s*c(?:onst(?:ant)?)?\s+/
obj = debug_eval($', binding)
unless obj.kind_of? Module
- stdout.print "should be Class/Module: ", $', "\n"
+ stdout.print "Should be Class/Module: ", $', "\n"
else
var_list(obj.constants, obj.module_eval{binding()})
end
@@ -184,7 +178,7 @@ class DEBUGGER__
else
obj = debug_eval(input, binding)
unless obj.kind_of? Module
- stdout.print "should be Class/Module: ", input, "\n"
+ stdout.print "Should be Class/Module: ", input, "\n"
else
len = 0
for v in obj.instance_methods.sort
@@ -235,12 +229,12 @@ class DEBUGGER__
case input
when /^\s*tr(?:ace)?(?:\s+(on|off))?$/
- if !defined?( $1 )
- @trace = !@trace
- elsif $1 == 'on'
- @trace = true
- else
- @trace = false
+ if defined?( $1 )
+ if $1 == 'on'
+ @trace = true
+ else
+ @trace = false
+ end
end
if @trace
stdout.print "Trace on\n"
@@ -271,7 +265,7 @@ class DEBUGGER__
when /^\s*b(?:reak)?$/
if break_points.find{|b| b[1] == 0}
n = 1
- stdout.print "breakpoints:\n"
+ stdout.print "Breakpoints:\n"
for b in break_points
if b[0] and b[1] == 0
stdout.printf " %d %s:%s\n", n, b[2], b[3]
@@ -282,7 +276,7 @@ class DEBUGGER__
if break_points.find{|b| b[1] == 1}
n = 1
stdout.print "\n"
- stdout.print "watchpoints:\n"
+ stdout.print "Watchpoints:\n"
for b in break_points
if b[0] and b[1] == 1
stdout.printf " %d %s\n", n, b[2]
@@ -291,7 +285,7 @@ class DEBUGGER__
end
end
if break_points.size == 0
- stdout.print "no breakpoints\n"
+ stdout.print "No breakpoints\n"
else
stdout.print "\n"
end
@@ -299,7 +293,7 @@ class DEBUGGER__
when /^\s*del(?:ete)?(?:\s+(\d+))?$/
pos = $1
unless pos
- input = readline("clear all breakpoints? (y/n) ", false)
+ input = readline("Clear all breakpoints? (y/n) ", false)
if input == "y"
for b in break_points
b[0] = false
@@ -326,7 +320,7 @@ class DEBUGGER__
when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
pos = $1
unless pos
- input = readline("clear all expressions? (y/n) ", false)
+ input = readline("Clear all expressions? (y/n) ", false)
if input == "y"
for d in display
d[0] = false
@@ -337,7 +331,7 @@ class DEBUGGER__
if display[pos-1]
display[pos-1][0] = false
else
- stdout.printf "display expression %d is not defined\n", pos
+ stdout.printf "Display expression %d is not defined\n", pos
end
end
@@ -397,7 +391,7 @@ class DEBUGGER__
frame_pos += lev
if frame_pos >= @frames.size
frame_pos = @frames.size - 1
- stdout.print "at toplevel\n"
+ stdout.print "At toplevel\n"
end
binding, binding_file, binding_line = @frames[frame_pos]
stdout.printf "#%d %s:%s\n", frame_pos, binding_file, binding_line
@@ -412,7 +406,7 @@ class DEBUGGER__
frame_pos -= lev
if frame_pos < 0
frame_pos = 0
- stdout.print "at stack bottom\n"
+ stdout.print "At stack bottom\n"
end
binding, binding_file, binding_line = @frames[frame_pos]
stdout.printf "#%d %s:%s\n", frame_pos, binding_file, binding_line
@@ -422,11 +416,29 @@ class DEBUGGER__
stdout.print "\"finish\" not meaningful in the outermost frame.\n"
else
@finish_pos = @frames.size - frame_pos
- p @finish_pos
frame_pos = 0
+ MUTEX.unlock
return
end
+ when /^\s*cat(?:ch)?(?:\s+(.+))?$/
+ if $1
+ excn = $1
+ if excn == 'off'
+ @catch = nil
+ stdout.print "Clear catchpoint.\n"
+ else
+ @catch = excn
+ stdout.printf "Set catchpoint %s.\n", @catch
+ end
+ else
+ if @catch
+ stdout.printf "Catchpoint %s.\n", @catch
+ else
+ stdout.print "No catchpoint.\n"
+ end
+ end
+
when /^\s*q(?:uit)?$/
input = readline("really quit? (y/n) ", false)
exit if input == "y"
@@ -444,27 +456,29 @@ class DEBUGGER__
end
when /^\s*p\s+/
- p debug_eval($', binding)
+ stdout.printf "%s\n", debug_eval($', binding)
- when /^\s*h(?:elp)?/
+ when /^\s*h(?:elp)?$/
debug_print_help()
else
v = debug_eval(input, binding)
- p v unless (v == nil)
+ stdout.printf "%s\n", v unless (v == nil)
end
end
end
end
def debug_print_help
- print <<EOHELP
+ stdout.print <<EOHELP
Debugger help v.-0.002b
Commands
b[reak] [file|method:]<line|method>
set breakpoint to some position
wat[ch] <expression> set watchpoint to some expression
+ cat[ch] <an Exception> set catchpoint to an exception
b[reak] list breakpoints
+ cat[ch] show catchpoint
del[ele][ nnn] delete some or all breakpoints
disp[lay] <expression> add expression into display expression list
undisp[lay][ nnn] delete one particular or all display expressions
@@ -549,7 +563,7 @@ EOHELP
end
end
else
- stdout.printf "no sourcefile available for %s\n", file
+ stdout.printf "No sourcefile available for %s\n", file
end
end
@@ -580,11 +594,11 @@ EOHELP
for b in break_points
if b[0]
if b[1] == 0 and b[2] == file and b[3] == pos
- stdout.printf "breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
+ stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
return true
elsif b[1] == 1
if debug_silent_eval(b[2], binding)
- stdout.printf "watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
+ stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
return true
end
end
@@ -596,22 +610,25 @@ EOHELP
end
def excn_handle(file, line, id, binding)
- p $!
+ stdout.printf "Exception `%s': %s\n", $!.type, $!
if $!.type <= SystemExit
set_trace_func nil
exit
end
+
MUTEX.lock
fs = @frames.size
tb = caller(0)[-fs..-1]
-
- stdout.printf "%s\n", $!
if tb
for i in tb
stdout.printf "\tfrom %s\n", i
end
end
- debug_command(file, line, id, binding)
+ if @catch and ($!.type.ancestors.find { |e| e.to_s == @catch })
+ debug_command(file, line, id, binding)
+ else
+ MUTEX.unlock
+ end
end
def trace_func(event, file, line, id, binding, klass)
@@ -781,8 +798,8 @@ EOHELP
end
end
- @stdout.printf "Debug.rb\n"
- @stdout.printf "Emacs support available.\n\n"
+ stdout.printf "Debug.rb\n"
+ stdout.printf "Emacs support available.\n\n"
set_trace_func proc{|event, file, line, id, binding,klass,*rest|
DEBUGGER__.context.trace_func event, file, line, id, binding,klass
}
diff --git a/lib/timeout.rb b/lib/timeout.rb
index 4e6f546e0c..dd7cb306cf 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -39,6 +39,12 @@ def timeout(sec)
yield sec
return true
ensure
- Thread.kill y if y.alive?
+ Thread.kill y if y and y.alive?
end
end
+
+if __FILE__ == $0
+ timeout(5) {
+ p 10
+ }
+end