Skip to content

Commit c14831d

Browse files
committed
merge revision(s) 17832:
* eval.c (rb_longjmp): duplicate the thrown exception to set backtrace if it was frozen. clear all raised flags. * eval.c (stack_check): leave clearing flag to rb_longjmp. * eval.c (rb_thread_set_raised, rb_thread_reset_raised): use generic flags. * eval.c (Init_Proc), gc.c (Init_GC): freeze preallocated special exceptions. * gc.c (rb_memerror): use thread raised flag instead of static flag, and raise nomem_error without backtrace if failed to make backtrace. [ruby-dev:34724] * gc.c (ruby_xmalloc): increase malloc_increase only if malloc succeeds. failed malloc size can be huge. it may increase malloc_limit too big which cause less GC and memory full. (ruby_xrealloc): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@17930 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 719f4c4 commit c14831d

File tree

5 files changed

+98
-42
lines changed

5 files changed

+98
-42
lines changed

ChangeLog

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
Mon Jul 7 15:02:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
2+
3+
* eval.c (rb_longjmp): duplicate the thrown exception to set backtrace
4+
if it was frozen. clear all raised flags.
5+
6+
* eval.c (stack_check): leave clearing flag to rb_longjmp.
7+
8+
* eval.c (rb_thread_set_raised, rb_thread_reset_raised): use generic
9+
flags.
10+
11+
* eval.c (Init_Proc), gc.c (Init_GC): freeze preallocated special exceptions.
12+
13+
* gc.c (rb_memerror): use thread raised flag instead of static flag,
14+
and raise nomem_error without backtrace if failed to make backtrace.
15+
[ruby-dev:34724]
16+
17+
* gc.c (ruby_xmalloc): increase malloc_increase only if malloc
18+
succeeds. failed malloc size can be huge. it may increase
19+
malloc_limit too big which cause less GC and memory full.
20+
(ruby_xrealloc): ditto.
21+
122
Mon Jul 7 12:23:05 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
223

324
* ext/win32ole/win32ole.c: avoid creating Ruby object during

eval.c

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,9 +1441,6 @@ int ruby_in_eval;
14411441
static void rb_thread_cleanup _((void));
14421442
static void rb_thread_wait_other_threads _((void));
14431443

1444-
static int thread_set_raised();
1445-
static int thread_reset_raised();
1446-
14471444
static int thread_no_ensure _((void));
14481445

14491446
static VALUE exception_error;
@@ -1462,8 +1459,10 @@ error_handle(ex)
14621459
int ex;
14631460
{
14641461
int status = EXIT_FAILURE;
1462+
rb_thread_t th = curr_thread;
14651463

1466-
if (thread_set_raised()) return EXIT_FAILURE;
1464+
if (rb_thread_set_raised(th))
1465+
return EXIT_FAILURE;
14671466
switch (ex & TAG_MASK) {
14681467
case 0:
14691468
status = EXIT_SUCCESS;
@@ -1516,7 +1515,7 @@ error_handle(ex)
15161515
rb_bug("Unknown longjmp status %d", ex);
15171516
break;
15181517
}
1519-
thread_reset_raised();
1518+
rb_thread_reset_raised(th);
15201519
return status;
15211520
}
15221521

@@ -2709,6 +2708,7 @@ call_trace_func(event, node, self, id, klass)
27092708
NODE *node_save;
27102709
VALUE srcfile;
27112710
const char *event_name;
2711+
rb_thread_t th = curr_thread;
27122712

27132713
if (!trace_func) return;
27142714
if (tracing) return;
@@ -2740,7 +2740,7 @@ call_trace_func(event, node, self, id, klass)
27402740
}
27412741
}
27422742
PUSH_TAG(PROT_NONE);
2743-
raised = thread_reset_raised();
2743+
raised = rb_thread_reset_raised(th);
27442744
if ((state = EXEC_TAG()) == 0) {
27452745
srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)");
27462746
event_name = get_event_name(event);
@@ -2752,7 +2752,7 @@ call_trace_func(event, node, self, id, klass)
27522752
klass),
27532753
Qundef, 0);
27542754
}
2755-
if (raised) thread_set_raised();
2755+
if (raised) rb_thread_set_raised(th);
27562756
POP_TAG();
27572757
POP_FRAME();
27582758

@@ -4571,8 +4571,9 @@ rb_longjmp(tag, mesg)
45714571
VALUE mesg;
45724572
{
45734573
VALUE at;
4574+
rb_thread_t th = curr_thread;
45744575

4575-
if (thread_set_raised()) {
4576+
if (rb_thread_set_raised(th)) {
45764577
ruby_errinfo = exception_error;
45774578
JUMP_TAG(TAG_FATAL);
45784579
}
@@ -4586,6 +4587,9 @@ rb_longjmp(tag, mesg)
45864587
at = get_backtrace(mesg);
45874588
if (NIL_P(at)) {
45884589
at = make_backtrace();
4590+
if (OBJ_FROZEN(mesg)) {
4591+
mesg = rb_obj_dup(mesg);
4592+
}
45894593
set_backtrace(mesg, at);
45904594
}
45914595
}
@@ -4611,7 +4615,7 @@ rb_longjmp(tag, mesg)
46114615
ruby_errinfo = mesg;
46124616
}
46134617
else if (status) {
4614-
thread_reset_raised();
4618+
rb_thread_reset_raised(th);
46154619
JUMP_TAG(status);
46164620
}
46174621
}
@@ -4626,10 +4630,19 @@ rb_longjmp(tag, mesg)
46264630
if (!prot_tag) {
46274631
error_print();
46284632
}
4629-
thread_reset_raised();
4633+
rb_thread_raised_clear(th);
46304634
JUMP_TAG(tag);
46314635
}
46324636

4637+
void
4638+
rb_exc_jump(mesg)
4639+
VALUE mesg;
4640+
{
4641+
rb_thread_raised_clear(rb_curr_thread);
4642+
ruby_errinfo = mesg;
4643+
JUMP_TAG(TAG_RAISE);
4644+
}
4645+
46334646
void
46344647
rb_exc_raise(mesg)
46354648
VALUE mesg;
@@ -5578,18 +5591,11 @@ rb_with_disable_interrupt(proc, data)
55785591
static void
55795592
stack_check()
55805593
{
5581-
static int overflowing = 0;
5594+
rb_thread_t th = rb_curr_thread;
55825595

5583-
if (!overflowing && ruby_stack_check()) {
5584-
int state;
5585-
overflowing = 1;
5586-
PUSH_TAG(PROT_NONE);
5587-
if ((state = EXEC_TAG()) == 0) {
5588-
rb_exc_raise(sysstack_error);
5589-
}
5590-
POP_TAG();
5591-
overflowing = 0;
5592-
JUMP_TAG(state);
5596+
if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
5597+
rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
5598+
rb_exc_raise(sysstack_error);
55935599
}
55945600
}
55955601

@@ -9987,11 +9993,14 @@ Init_Proc()
99879993

99889994
rb_global_variable(&exception_error);
99899995
exception_error = rb_exc_new2(rb_eFatal, "exception reentered");
9996+
OBJ_TAINT(exception_error);
9997+
OBJ_FREEZE(exception_error);
99909998

99919999
rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError);
999210000
rb_global_variable(&sysstack_error);
999310001
sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep");
999410002
OBJ_TAINT(sysstack_error);
10003+
OBJ_FREEZE(sysstack_error);
999510004

999610005
rb_cProc = rb_define_class("Proc", rb_cObject);
999710006
rb_undef_alloc_func(rb_cProc);
@@ -10169,10 +10178,9 @@ extern VALUE rb_last_status;
1016910178
# endif
1017010179
#endif
1017110180

10172-
#define THREAD_RAISED 0x200 /* temporary flag */
1017310181
#define THREAD_TERMINATING 0x400 /* persistent flag */
10174-
#define THREAD_NO_ENSURE 0x800 /* persistent flag */
10175-
#define THREAD_FLAGS_MASK 0xc00 /* mask for persistent flags */
10182+
#define THREAD_NO_ENSURE 0x800 /* persistent flag */
10183+
#define THREAD_FLAGS_MASK 0xfc00 /* mask for persistent flags */
1017610184

1017710185
#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
1017810186
#define END_FOREACH_FROM(f,x) } while (x != f)
@@ -10224,19 +10232,25 @@ struct thread_status_t {
1022410232
(dst)->join = (src)->join, \
1022510233
0)
1022610234

10227-
static int
10228-
thread_set_raised()
10235+
int
10236+
rb_thread_set_raised(th)
10237+
rb_thread_t th;
1022910238
{
10230-
if (curr_thread->flags & THREAD_RAISED) return 1;
10231-
curr_thread->flags |= THREAD_RAISED;
10239+
if (th->flags & RAISED_EXCEPTION) {
10240+
return 1;
10241+
}
10242+
th->flags |= RAISED_EXCEPTION;
1023210243
return 0;
1023310244
}
1023410245

10235-
static int
10236-
thread_reset_raised()
10246+
int
10247+
rb_thread_reset_raised(th)
10248+
rb_thread_t th;
1023710249
{
10238-
if (!(curr_thread->flags & THREAD_RAISED)) return 0;
10239-
curr_thread->flags &= ~THREAD_RAISED;
10250+
if (!(th->flags & RAISED_EXCEPTION)) {
10251+
return 0;
10252+
}
10253+
th->flags &= ~RAISED_EXCEPTION;
1024010254
return 1;
1024110255
}
1024210256

@@ -11374,7 +11388,7 @@ rb_thread_join(th, limit)
1137411388
if (!rb_thread_dead(th)) return Qfalse;
1137511389
}
1137611390

11377-
if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED)) {
11391+
if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION)) {
1137811392
VALUE oldbt = get_backtrace(th->errinfo);
1137911393
VALUE errat = make_backtrace();
1138011394
VALUE errinfo = rb_obj_dup(th->errinfo);
@@ -12250,7 +12264,7 @@ rb_thread_start_0(fn, arg, th)
1225012264
}
1225112265

1225212266
if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
12253-
th->flags |= THREAD_RAISED;
12267+
th->flags |= RAISED_EXCEPTION;
1225412268
if (state == TAG_FATAL) {
1225512269
/* fatal error within this thread, need to stop whole script */
1225612270
main_thread->errinfo = ruby_errinfo;
@@ -12468,7 +12482,7 @@ rb_thread_status(thread)
1246812482
rb_thread_t th = rb_thread_check(thread);
1246912483

1247012484
if (rb_thread_dead(th)) {
12471-
if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED))
12485+
if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION))
1247212486
return Qnil;
1247312487
return Qfalse;
1247412488
}

gc.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,22 @@ static void garbage_collect();
7878

7979
int ruby_gc_stress = 0;
8080

81+
NORETURN(void rb_exc_jump _((VALUE)));
82+
8183
void
8284
rb_memerror()
8385
{
84-
static int recurse = 0;
86+
rb_thread_t th = rb_curr_thread;
8587

86-
if (!nomem_error || (recurse > 0 && rb_safe_level() < 4)) {
88+
if (!nomem_error ||
89+
(rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) {
8790
fprintf(stderr, "[FATAL] failed to allocate memory\n");
8891
exit(1);
8992
}
90-
recurse++;
93+
if (rb_thread_raised_p(th, RAISED_NOMEMORY)) {
94+
rb_exc_jump(nomem_error);
95+
}
96+
rb_thread_raised_set(th, RAISED_NOMEMORY);
9197
rb_exc_raise(nomem_error);
9298
}
9399

@@ -136,9 +142,8 @@ ruby_xmalloc(size)
136142
rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
137143
}
138144
if (size == 0) size = 1;
139-
malloc_increase += size;
140145

141-
if (ruby_gc_stress || malloc_increase > malloc_limit) {
146+
if (ruby_gc_stress || (malloc_increase+size) > malloc_limit) {
142147
garbage_collect();
143148
}
144149
RUBY_CRITICAL(mem = malloc(size));
@@ -149,6 +154,7 @@ ruby_xmalloc(size)
149154
rb_memerror();
150155
}
151156
}
157+
malloc_increase += size;
152158

153159
return mem;
154160
}
@@ -177,7 +183,6 @@ ruby_xrealloc(ptr, size)
177183
}
178184
if (!ptr) return xmalloc(size);
179185
if (size == 0) size = 1;
180-
malloc_increase += size;
181186
if (ruby_gc_stress) garbage_collect();
182187
RUBY_CRITICAL(mem = realloc(ptr, size));
183188
if (!mem) {
@@ -187,6 +192,7 @@ ruby_xrealloc(ptr, size)
187192
rb_memerror();
188193
}
189194
}
195+
malloc_increase += size;
190196

191197
return mem;
192198
}
@@ -2110,6 +2116,8 @@ Init_GC()
21102116

21112117
rb_global_variable(&nomem_error);
21122118
nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
2119+
OBJ_TAINT(nomem_error);
2120+
OBJ_FREEZE(nomem_error);
21132121

21142122
rb_define_method(rb_mKernel, "hash", rb_obj_id, 0);
21152123
rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0);

node.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,19 @@ extern VALUE (*ruby_sandbox_restore)_((rb_thread_t));
468468
extern rb_thread_t rb_curr_thread;
469469
extern rb_thread_t rb_main_thread;
470470

471+
enum {
472+
RAISED_EXCEPTION = 0x1000,
473+
RAISED_STACKOVERFLOW = 0x2000,
474+
RAISED_NOMEMORY = 0x4000,
475+
RAISED_MASK = 0xf000
476+
};
477+
int rb_thread_set_raised(rb_thread_t th);
478+
int rb_thread_reset_raised(rb_thread_t th);
479+
#define rb_thread_raised_set(th, f) ((th)->flags |= (f))
480+
#define rb_thread_raised_reset(th, f) ((th)->flags &= ~(f))
481+
#define rb_thread_raised_p(th, f) (((th)->flags & (f)) != 0)
482+
#define rb_thread_raised_clear(th) ((th)->flags = 0)
483+
471484
#if defined(__cplusplus)
472485
} /* extern "C" { */
473486
#endif

version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define RUBY_RELEASE_DATE "2008-07-07"
33
#define RUBY_VERSION_CODE 187
44
#define RUBY_RELEASE_CODE 20080707
5-
#define RUBY_PATCHLEVEL 48
5+
#define RUBY_PATCHLEVEL 49
66

77
#define RUBY_VERSION_MAJOR 1
88
#define RUBY_VERSION_MINOR 8

0 commit comments

Comments
 (0)