Ruby  2.5.0dev(2017-10-22revision60238)
eval_error.c
Go to the documentation of this file.
1 /* -*-c-*- */
2 /*
3  * included by eval.c
4  */
5 
6 #ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
7 #define warn_print(x) RB_GNUC_EXTENSION_BLOCK( \
8  (__builtin_constant_p(x)) ? \
9  rb_write_error2((x), (long)strlen(x)) : \
10  rb_write_error(x) \
11 )
12 #else
13 #define warn_print(x) rb_write_error(x)
14 #endif
15 #define warn_print2(x,l) rb_write_error2((x),(l))
16 #define warn_print_str(x) rb_write_error_str(x)
17 
18 static VALUE error_pos_str(void);
19 
20 static void
21 error_pos(void)
22 {
23  VALUE str = error_pos_str();
24  if (!NIL_P(str)) {
25  warn_print_str(str);
26  }
27 }
28 
29 static VALUE
30 error_pos_str(void)
31 {
32  int sourceline;
33  VALUE sourcefile = rb_source_location(&sourceline);
34 
35  if (sourcefile) {
36  ID caller_name;
37  if (sourceline == 0) {
38  return rb_sprintf("%"PRIsVALUE": ", sourcefile);
39  }
40  else if ((caller_name = rb_frame_callee()) != 0) {
41  return rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"': ",
42  sourcefile, sourceline,
43  rb_id2str(caller_name));
44  }
45  else {
46  return rb_sprintf("%"PRIsVALUE":%d: ", sourcefile, sourceline);
47  }
48  }
49  return Qnil;
50 }
51 
52 static void
53 set_backtrace(VALUE info, VALUE bt)
54 {
55  ID set_backtrace = rb_intern("set_backtrace");
56 
57  if (rb_backtrace_p(bt)) {
58  if (rb_method_basic_definition_p(CLASS_OF(info), set_backtrace)) {
59  rb_exc_set_backtrace(info, bt);
60  return;
61  }
62  else {
63  bt = rb_backtrace_to_str_ary(bt);
64  }
65  }
66  rb_check_funcall(info, set_backtrace, 1, &bt);
67 }
68 
69 static void
70 error_print(rb_thread_t *th)
71 {
73 }
74 
75 static void
76 print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg)
77 {
78  const char *einfo = "";
79  long elen = 0;
80  VALUE mesg;
81 
82  if (emesg != Qundef) {
83  if (NIL_P(errat) || RARRAY_LEN(errat) == 0 ||
84  NIL_P(mesg = RARRAY_AREF(errat, 0))) {
85  error_pos();
86  }
87  else {
88  warn_print_str(mesg);
89  warn_print(": ");
90  }
91 
92  if (!NIL_P(emesg)) {
93  einfo = RSTRING_PTR(emesg);
94  elen = RSTRING_LEN(emesg);
95  }
96  }
97 
98  if (eclass == rb_eRuntimeError && elen == 0) {
99  warn_print("unhandled exception\n");
100  }
101  else {
102  VALUE epath;
103 
104  epath = rb_class_name(eclass);
105  if (elen == 0) {
106  warn_print_str(epath);
107  warn_print("\n");
108  }
109  else {
110  const char *tail = 0;
111  long len = elen;
112 
113  if (RSTRING_PTR(epath)[0] == '#')
114  epath = 0;
115  if ((tail = memchr(einfo, '\n', elen)) != 0) {
116  len = tail - einfo;
117  tail++; /* skip newline */
118  }
119  warn_print_str(tail ? rb_str_subseq(emesg, 0, len) : emesg);
120  if (epath) {
121  warn_print(" (");
122  warn_print_str(epath);
123  warn_print(")\n");
124  }
125  if (tail) {
126  warn_print_str(rb_str_subseq(emesg, tail - einfo, elen - len - 1));
127  }
128  if (tail ? einfo[elen-1] != '\n' : !epath) warn_print2("\n", 1);
129  }
130  }
131 }
132 
133 static void
134 print_backtrace(const VALUE eclass, const VALUE errat, int reverse)
135 {
136  if (!NIL_P(errat)) {
137  long i;
138  long len = RARRAY_LEN(errat);
139  int skip = eclass == rb_eSysStackError;
140  const int threshold = 1000000000;
141  int width = ((int)log10((double)(len > threshold ?
142  ((len - 1) / threshold) :
143  len - 1)) +
144  (len < threshold ? 0 : 9) + 1);
145 
146 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
147 #define TRACE_HEAD 8
148 #define TRACE_TAIL 5
149 
150  for (i = 1; i < len; i++) {
151  VALUE line = RARRAY_AREF(errat, reverse ? len - i : i);
152  if (RB_TYPE_P(line, T_STRING)) {
153  VALUE str = rb_str_new_cstr("\t");
154  if (reverse) rb_str_catf(str, "%*ld: ", width, len - i);
155  warn_print_str(rb_str_catf(str, "from %"PRIsVALUE"\n", line));
156  }
157  if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
158  warn_print_str(rb_sprintf("\t ... %ld levels...\n",
159  len - TRACE_HEAD - TRACE_TAIL));
160  i = len - TRACE_TAIL;
161  }
162  }
163  }
164 }
165 
166 void
167 rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
168 {
169  volatile VALUE errat = Qundef;
170  volatile int raised_flag = th->ec.raised_flag;
171  volatile VALUE eclass = Qundef, emesg = Qundef;
172 
173  if (NIL_P(errinfo))
174  return;
176 
177  TH_PUSH_TAG(th);
178  if (TH_EXEC_TAG() == TAG_NONE) {
179  errat = rb_get_backtrace(errinfo);
180  }
181  else if (errat == Qundef) {
182  errat = Qnil;
183  }
184  else if (eclass == Qundef || emesg != Qundef) {
185  goto error;
186  }
187  if ((eclass = CLASS_OF(errinfo)) != Qundef) {
188  VALUE e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0);
189  if (e != Qundef) {
190  if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
191  emesg = e;
192  }
193  }
194  if (rb_stderr_tty_p()) {
195  warn_print("Traceback (most recent call last):\n");
196  print_backtrace(eclass, errat, TRUE);
197  print_errinfo(eclass, errat, emesg);
198  }
199  else {
200  print_errinfo(eclass, errat, emesg);
201  print_backtrace(eclass, errat, FALSE);
202  }
203  error:
204  TH_POP_TAG();
205  th->ec.errinfo = errinfo;
206  rb_thread_raised_set(th, raised_flag);
207 }
208 
209 #define undef_mesg_for(v, k) rb_fstring_cstr("undefined"v" method `%1$s' for "k" `%2$s'")
210 #define undef_mesg(v) ( \
211  is_mod ? \
212  undef_mesg_for(v, "module") : \
213  undef_mesg_for(v, "class"))
214 
215 void
217 {
218  const int is_mod = RB_TYPE_P(klass, T_MODULE);
219  VALUE mesg;
220  switch (visi & METHOD_VISI_MASK) {
221  case METHOD_VISI_UNDEF:
222  case METHOD_VISI_PUBLIC: mesg = undef_mesg(""); break;
223  case METHOD_VISI_PRIVATE: mesg = undef_mesg(" private"); break;
224  case METHOD_VISI_PROTECTED: mesg = undef_mesg(" protected"); break;
225  default: UNREACHABLE;
226  }
227  rb_name_err_raise_str(mesg, klass, ID2SYM(id));
228 }
229 
230 void
232 {
233  const int is_mod = RB_TYPE_P(klass, T_MODULE);
234  rb_name_err_raise_str(undef_mesg(""), klass, name);
235 }
236 
237 #define inaccessible_mesg_for(v, k) rb_fstring_cstr("method `%1$s' for "k" `%2$s' is "v)
238 #define inaccessible_mesg(v) ( \
239  is_mod ? \
240  inaccessible_mesg_for(v, "module") : \
241  inaccessible_mesg_for(v, "class"))
242 
243 void
245 {
246  const int is_mod = RB_TYPE_P(klass, T_MODULE);
247  VALUE mesg;
248  switch (visi & METHOD_VISI_MASK) {
249  case METHOD_VISI_UNDEF:
250  case METHOD_VISI_PUBLIC: mesg = inaccessible_mesg(""); break;
251  case METHOD_VISI_PRIVATE: mesg = inaccessible_mesg(" private"); break;
252  case METHOD_VISI_PROTECTED: mesg = inaccessible_mesg(" protected"); break;
253  default: UNREACHABLE;
254  }
255  rb_name_err_raise_str(mesg, klass, ID2SYM(id));
256 }
257 
258 static int
259 sysexit_status(VALUE err)
260 {
261  VALUE st = rb_ivar_get(err, id_status);
262  return NUM2INT(st);
263 }
264 
265 #define unknown_longjmp_status(status) \
266  rb_bug("Unknown longjmp status %d", status)
267 
268 static int
269 error_handle(int ex)
270 {
271  int status = EXIT_FAILURE;
272  rb_thread_t *th = GET_THREAD();
273 
274  if (rb_threadptr_set_raised(th))
275  return EXIT_FAILURE;
276  switch (ex & TAG_MASK) {
277  case 0:
278  status = EXIT_SUCCESS;
279  break;
280 
281  case TAG_RETURN:
282  error_pos();
283  warn_print("unexpected return\n");
284  break;
285  case TAG_NEXT:
286  error_pos();
287  warn_print("unexpected next\n");
288  break;
289  case TAG_BREAK:
290  error_pos();
291  warn_print("unexpected break\n");
292  break;
293  case TAG_REDO:
294  error_pos();
295  warn_print("unexpected redo\n");
296  break;
297  case TAG_RETRY:
298  error_pos();
299  warn_print("retry outside of rescue clause\n");
300  break;
301  case TAG_THROW:
302  /* TODO: fix me */
303  error_pos();
304  warn_print("unexpected throw\n");
305  break;
306  case TAG_RAISE: {
307  VALUE errinfo = th->ec.errinfo;
308  if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
309  status = sysexit_status(errinfo);
310  }
311  else if (rb_obj_is_instance_of(errinfo, rb_eSignal) &&
312  rb_ivar_get(errinfo, id_signo) != INT2FIX(SIGSEGV)) {
313  /* no message when exiting by signal */
314  }
315  else {
316  rb_threadptr_error_print(th, errinfo);
317  }
318  break;
319  }
320  case TAG_FATAL:
321  error_print(th);
322  break;
323  default:
325  break;
326  }
328  return status;
329 }
int rb_stderr_tty_p(void)
Definition: io.c:7602
#define warn_print2(x, l)
Definition: eval_error.c:15
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define FALSE
Definition: nkf.h:174
void rb_print_undef(VALUE klass, ID id, rb_method_visibility_t visi)
Definition: eval_error.c:216
#define NUM2INT(x)
Definition: ruby.h:684
#define TAG_NONE
Definition: vm_core.h:164
#define CLASS_OF(v)
Definition: ruby.h:453
#define rb_name_err_raise_str(mesg, recv, name)
Definition: internal.h:1166
#define T_MODULE
Definition: ruby.h:494
#define rb_id2str(id)
Definition: vm_backtrace.c:29
#define UNREACHABLE
Definition: ruby.h:46
#define EXIT_SUCCESS
Definition: error.c:37
void rb_print_undef_str(VALUE klass, VALUE name)
Definition: eval_error.c:231
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1210
#define TH_EXEC_TAG()
Definition: eval_intern.h:198
#define TAG_NEXT
Definition: vm_core.h:167
#define GET_THREAD()
Definition: vm_core.h:1583
#define id_signo
Definition: eval.c:29
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
Definition: object.c:842
#define TH_POP_TAG()
Definition: eval_intern.h:138
VALUE rb_eSignal
Definition: error.c:797
VALUE rb_class_name(VALUE)
Definition: variable.c:444
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2173
VALUE rb_eSysStackError
Definition: eval.c:25
#define undef_mesg(v)
Definition: eval_error.c:210
#define NIL_P(v)
Definition: ruby.h:451
rb_method_visibility_t
Definition: method.h:26
void rb_print_inaccessible(VALUE klass, ID id, rb_method_visibility_t visi)
Definition: eval_error.c:244
#define id_status
Definition: error.c:831
#define warn_print_str(x)
Definition: eval_error.c:16
#define TRACE_MAX
VALUE rb_obj_is_instance_of(VALUE, VALUE)
call-seq: obj.instance_of?(class) -> true or false
Definition: object.c:798
int err
Definition: win32.c:135
void rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
Definition: eval_error.c:167
#define EXIT_FAILURE
Definition: eval_intern.h:33
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:410
#define TAG_MASK
Definition: vm_core.h:173
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:288
VALUE rb_backtrace_to_str_ary(VALUE obj)
Definition: vm_backtrace.c:578
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2406
#define TAG_REDO
Definition: vm_core.h:169
#define RSTRING_LEN(str)
Definition: ruby.h:971
#define TRUE
Definition: nkf.h:175
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt)
Definition: error.c:1083
#define TRACE_HEAD
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:285
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define TAG_FATAL
Definition: vm_core.h:172
#define Qnil
Definition: ruby.h:438
#define TRACE_TAIL
unsigned long VALUE
Definition: ruby.h:85
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2183
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:131
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:389
VALUE rb_str_new_cstr(const char *)
Definition: string.c:771
register unsigned int len
Definition: zonetab.h:51
#define RSTRING_PTR(str)
Definition: ruby.h:975
#define TAG_RETRY
Definition: vm_core.h:168
VALUE rb_get_backtrace(VALUE exc)
Definition: error.c:1004
#define INT2FIX(i)
Definition: ruby.h:232
#define TAG_THROW
Definition: vm_core.h:171
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
ID rb_frame_callee(void)
The name of the current method.
Definition: eval.c:1120
VALUE rb_eRuntimeError
Definition: error.c:800
VALUE rb_eSystemExit
Definition: error.c:795
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1492
VALUE rb_check_string_type(VALUE)
Definition: string.c:2246
#define inaccessible_mesg(v)
Definition: eval_error.c:238
#define T_STRING
Definition: ruby.h:496
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1879
#define TAG_RETURN
Definition: vm_core.h:165
rb_execution_context_t ec
Definition: vm_core.h:790
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:383
VALUE rb_source_location(int *pline)
Definition: vm.c:1297
#define warn_print(x)
Definition: eval_error.c:13
#define TAG_BREAK
Definition: vm_core.h:166
#define rb_intern(str)
#define TAG_RAISE
Definition: vm_core.h:170
#define Qundef
Definition: ruby.h:439
#define unknown_longjmp_status(status)
Definition: eval_error.c:265