/********************************************************************** debug.c - $Author$ created at: 04/08/25 02:31:54 JST Copyright (C) 2004-2007 Koichi Sasada **********************************************************************/ #include "ruby/ruby.h" #include "ruby/encoding.h" #include "ruby/util.h" #include "debug.h" #include "eval_intern.h" #include "vm_core.h" #include "id.h" /* for gdb */ static const union { enum ruby_special_consts special_consts; enum ruby_value_type value_type; enum ruby_tag_type tag_type; enum node_type node_type; enum ruby_method_ids method_ids; enum { RUBY_ENCODING_INLINE_MAX = ENCODING_INLINE_MAX, RUBY_ENCODING_SHIFT = ENCODING_SHIFT, RUBY_ENCODING_MASK = ENCODING_MASK, RUBY_ENC_CODERANGE_MASK = ENC_CODERANGE_MASK, RUBY_ENC_CODERANGE_UNKNOWN = ENC_CODERANGE_UNKNOWN, RUBY_ENC_CODERANGE_7BIT = ENC_CODERANGE_7BIT, RUBY_ENC_CODERANGE_VALID = ENC_CODERANGE_VALID, RUBY_ENC_CODERANGE_BROKEN = ENC_CODERANGE_BROKEN, RUBY_FL_MARK = FL_MARK, RUBY_FL_REMENBERED_SET = FL_REMEMBERED_SET, RUBY_FL_FINALIZE = FL_FINALIZE, RUBY_FL_TAINT = FL_TAINT, RUBY_FL_UNTRUSTED = FL_UNTRUSTED, RUBY_FL_EXIVAR = FL_EXIVAR, RUBY_FL_FREEZE = FL_FREEZE, RUBY_FL_SINGLETON = FL_SINGLETON, RUBY_FL_USER0 = FL_USER0, RUBY_FL_USER1 = FL_USER1, RUBY_FL_USER2 = FL_USER2, RUBY_FL_USER3 = FL_USER3, RUBY_FL_USER4 = FL_USER4, RUBY_FL_USER5 = FL_USER5, RUBY_FL_USER6 = FL_USER6, RUBY_FL_USER7 = FL_USER7, RUBY_FL_USER8 = FL_USER8, RUBY_FL_USER9 = FL_USER9, RUBY_FL_USER10 = FL_USER10, RUBY_FL_USER11 = FL_USER11, RUBY_FL_USER12 = FL_USER12, RUBY_FL_USER13 = FL_USER13, RUBY_FL_USER14 = FL_USER14, RUBY_FL_USER15 = FL_USER15, RUBY_FL_USER16 = FL_USER16, RUBY_FL_USER17 = FL_USER17, RUBY_FL_USER18 = FL_USER18, RUBY_FL_USHIFT = FL_USHIFT, RUBY_NODE_TYPESHIFT = NODE_TYPESHIFT, RUBY_NODE_TYPEMASK = NODE_TYPEMASK, RUBY_NODE_LSHIFT = NODE_LSHIFT, RUBY_NODE_LMASK = NODE_LMASK, RUBY_NODE_FL_NEWLINE = NODE_FL_NEWLINE } various; } dummy_gdb_enums; const VALUE RUBY_FL_USER19 = FL_USER19; int ruby_debug_print_indent(int level, int debug_level, int indent_level) { if (level < debug_level) { fprintf(stderr, "%*s", indent_level, ""); fflush(stderr); return Qtrue; } return Qfalse; } void ruby_debug_printf(const char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); } VALUE ruby_debug_print_value(int level, int debug_level, const char *header, VALUE obj) { if (level < debug_level) { VALUE str; str = rb_inspect(obj); fprintf(stderr, "DBG> %s: %s\n", header, obj == (VALUE)(SIGNED_VALUE)-1 ? "" : StringValueCStr(str)); fflush(stderr); } return obj; } void ruby_debug_print_v(VALUE v) { ruby_debug_print_value(0, 1, "", v); } ID ruby_debug_print_id(int level, int debug_level, const char *header, ID id) { if (level < debug_level) { fprintf(stderr, "DBG> %s: %s\n", header, rb_id2name(id)); fflush(stderr); } return id; } NODE * ruby_debug_print_node(int level, int debug_level, const char *header, const NODE *node) { if (level < debug_level) { fprintf(stderr, "DBG> %s: %s (%lu)\n", header, ruby_node_name(nd_type(node)), nd_line(node)); } return (NODE *)node; } void ruby_debug_breakpoint(void) { /* */ } #ifdef RUBY_DEBUG_ENV static void set_debug_option(const char *str, int len, void *arg) { #define SET_WHEN(name, var) do { \ if (len == sizeof(name) - 1 && \ strncmp(str, name, len) == 0) { \ extern int var; \ var = 1; \ return; \ } \ } while (0) SET_WHEN("gc_stress", *ruby_initial_gc_stress_ptr); SET_WHEN("core", ruby_enable_coredump); #if defined _WIN32 && defined _MSC_VER && _MSC_VER >= 1400 SET_WHEN("rtc_error", ruby_w32_rtc_error); #endif fprintf(stderr, "unexpected debug option: %.*s\n", len, str); } void ruby_set_debug_option(const char *str) { ruby_each_words(str, set_debug_option, 0); } #endif 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
# = timeout.rb
#
# execution timeout
#
# = Synopsis
#
# require 'timeout'
# status = Timeout::timeout(5) {
# # Something that should be interrupted if it takes too much time...
# }
#
# = Description
#
# A way of performing a potentially long-running operation in a thread, and terminating
# it's execution if it hasn't finished by a fixed amount of time.
#
# Previous versions of timeout didn't provide use a module for namespace. This version
# provides both Timeout.timeout, and a backwards-compatible #timeout.
#
# = Copyright
#
# Copyright:: (C) 2000 Network Applied Communication Laboratory, Inc.
# Copyright:: (C) 2000 Information-technology Promotion Agency, Japan
module Timeout
# Raised by Timeout#timeout when the block times out.
class Error < RuntimeError
end
class ExitException < ::Exception # :nodoc:
end
THIS_FILE = /\A#{Regexp.quote(__FILE__)}:/o
CALLER_OFFSET = ((c = caller[0]) && THIS_FILE =~ c) ? 1 : 0
# Executes the method's block. If the block execution terminates before
# +sec+ seconds has passed, it returns the result value of the block.
# If not, it terminates the execution and raises +exception+ (which defaults
# to Timeout::Error).
#
# Note that this is both a method of module Timeout, so you can 'include Timeout'
# into your classes so they have a #timeout method, as well as a module method,
# so you can call it directly as Timeout.timeout().
def timeout(sec, klass = nil) #:yield: +sec+
return yield(sec) if sec == nil or sec.zero?
exception = klass || Class.new(ExitException)
begin
x = Thread.current
y = Thread.start {
sleep sec
x.raise exception, "execution expired" if x.alive?
}
return yield(sec)
rescue exception => e
rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o
(bt = e.backtrace).reject! {|m| rej =~ m}
level = -caller(CALLER_OFFSET).size
while THIS_FILE =~ bt[level]
bt.delete_at(level)
level += 1
end
raise if klass # if exception class is specified, it
# would be expected outside.
raise Error, e.message, e.backtrace
ensure
if y and y.alive?
y.kill
y.join # make sure y is dead.
end
end
end
module_function :timeout
end
# Identical to:
#
# Timeout::timeout(n, e, &block).
#
# Defined for backwards compatibility with earlier versions of timeout.rb, see
# Timeout#timeout.
def timeout(n, e = nil, &block)
Timeout::timeout(n, e, &block)
end
# Another name for Timeout::Error, defined for backwards compatibility with
# earlier versions of timeout.rb.
TimeoutError = Timeout::Error
if __FILE__ == $0
p timeout(5) {
45
}
p timeout(5, TimeoutError) {
45
}
p timeout(nil) {
54
}
p timeout(0) {
54
}
p timeout(5) {
loop {
p 10
sleep 1
}
}
end