Skip to content

Commit 50b224d

Browse files
committed
* eval.c, intern.h, ext/thread/thread.c: should not free queue while
any live threads are waiting. [ruby-dev:30653] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@13495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 13d5a28 commit 50b224d

File tree

4 files changed

+25
-33
lines changed

4 files changed

+25
-33
lines changed

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Sun Sep 23 07:49:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
2+
3+
* eval.c, intern.h, ext/thread/thread.c: should not free queue while
4+
any live threads are waiting. [ruby-dev:30653]
5+
16
Sun Sep 23 06:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
27

38
* ext/stringio/stringio.c (strio_init): separate from strio_initialize

eval.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6825,7 +6825,6 @@ rb_load(fname, wrap)
68256825
volatile VALUE self = ruby_top_self;
68266826
NODE *volatile last_node;
68276827
NODE *saved_cref = ruby_cref;
6828-
TMP_PROTECT;
68296828

68306829
if (wrap && ruby_safe_level >= 4) {
68316830
StringValue(fname);

ext/thread/thread.c

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ static VALUE rb_cSizedQueue;
2424
static VALUE set_critical(VALUE value);
2525

2626
static VALUE
27-
thread_exclusive_do(void)
27+
thread_exclusive(VALUE (*func)(ANYARGS), VALUE arg)
2828
{
29-
rb_thread_critical = 1;
29+
VALUE critical = rb_thread_critical;
3030

31-
return rb_yield(Qundef);
31+
rb_thread_critical = 1;
32+
return rb_ensure(func, arg, set_critical, (VALUE)critical);
3233
}
3334

3435
/*
@@ -43,7 +44,7 @@ thread_exclusive_do(void)
4344
static VALUE
4445
rb_thread_exclusive(void)
4546
{
46-
return rb_ensure(thread_exclusive_do, Qundef, set_critical, rb_thread_critical);
47+
return thread_exclusive(rb_yield, Qundef);
4748
}
4849

4950
typedef struct _Entry {
@@ -147,7 +148,7 @@ shift_list(List *list)
147148
VALUE value;
148149

149150
entry = list->entries;
150-
if (!entry) return Qundef;
151+
if (!entry) return Qnil;
151152

152153
list->entries = entry->next;
153154
if (entry == list->last_entry) {
@@ -269,20 +270,12 @@ wait_list(List *list)
269270
}
270271

271272
static void
272-
assert_no_survivors(List *waiting, const char *label, void *addr)
273+
kill_waiting_threads(List *waiting)
273274
{
274275
Entry *entry;
275-
VALUE ths = 0;
276276

277277
for (entry = waiting->entries; entry; entry = entry->next) {
278-
if (RTEST(wake_thread(entry->value))) {
279-
if (!ths) ths = rb_ary_new();
280-
rb_ary_push(ths, entry->value);
281-
}
282-
}
283-
if (ths) {
284-
rb_bug("%s %p freed with live thread(s) %s waiting",
285-
label, addr, RSTRING_PTR(rb_inspect(ths)));
278+
rb_thread_kill(entry->value);
286279
}
287280
}
288281

@@ -334,7 +327,7 @@ finalize_mutex(Mutex *mutex)
334327
static void
335328
free_mutex(Mutex *mutex)
336329
{
337-
assert_no_survivors(&mutex->waiting, "mutex", mutex);
330+
kill_waiting_threads(&mutex->waiting);
338331
finalize_mutex(mutex);
339332
xfree(mutex);
340333
}
@@ -493,10 +486,8 @@ set_critical(VALUE value)
493486
static VALUE
494487
unlock_mutex(Mutex *mutex)
495488
{
496-
VALUE waking;
489+
VALUE waking = thread_exclusive(unlock_mutex_inner, (VALUE)mutex);
497490

498-
rb_thread_critical = 1;
499-
waking = rb_ensure(unlock_mutex_inner, (VALUE)mutex, set_critical, 0);
500491
if (!RTEST(waking)) {
501492
return Qfalse;
502493
}
@@ -544,10 +535,9 @@ rb_mutex_exclusive_unlock(VALUE self)
544535
VALUE waking;
545536
Data_Get_Struct(self, Mutex, mutex);
546537

547-
rb_thread_critical = 1;
548-
waking = rb_ensure(rb_mutex_exclusive_unlock_inner, (VALUE)mutex, set_critical, 0);
538+
waking = thread_exclusive(rb_mutex_exclusive_unlock_inner, (VALUE)mutex);
549539

550-
if (waking == Qundef || !RTEST(waking)) {
540+
if (!RTEST(waking)) {
551541
return Qnil;
552542
}
553543

@@ -622,7 +612,7 @@ finalize_condvar(ConditionVariable *condvar)
622612
static void
623613
free_condvar(ConditionVariable *condvar)
624614
{
625-
assert_no_survivors(&condvar->waiting, "condition variable", condvar);
615+
kill_waiting_threads(&condvar->waiting);
626616
finalize_condvar(condvar);
627617
xfree(condvar);
628618
}
@@ -732,8 +722,7 @@ rb_condvar_broadcast(VALUE self)
732722

733723
Data_Get_Struct(self, ConditionVariable, condvar);
734724

735-
rb_thread_critical = 1;
736-
rb_ensure(wake_all, (VALUE)&condvar->waiting, set_critical, 0);
725+
thread_exclusive(wake_all, (VALUE)&condvar->waiting);
737726
rb_thread_schedule();
738727

739728
return self;
@@ -750,9 +739,8 @@ rb_condvar_broadcast(VALUE self)
750739
static void
751740
signal_condvar(ConditionVariable *condvar)
752741
{
753-
VALUE waking;
754-
rb_thread_critical = 1;
755-
waking = rb_ensure(wake_one, (VALUE)&condvar->waiting, set_critical, 0);
742+
VALUE waking = thread_exclusive(wake_one, (VALUE)&condvar->waiting);
743+
756744
if (RTEST(waking)) {
757745
run_thread(waking);
758746
}
@@ -827,9 +815,9 @@ finalize_queue(Queue *queue)
827815
static void
828816
free_queue(Queue *queue)
829817
{
830-
assert_no_survivors(&queue->mutex.waiting, "queue", queue);
831-
assert_no_survivors(&queue->space_available.waiting, "queue", queue);
832-
assert_no_survivors(&queue->value_available.waiting, "queue", queue);
818+
kill_waiting_threads(&queue->mutex.waiting);
819+
kill_waiting_threads(&queue->space_available.waiting);
820+
kill_waiting_threads(&queue->value_available.waiting);
833821
finalize_queue(queue);
834822
xfree(queue);
835823
}

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 "2007-09-23"
33
#define RUBY_VERSION_CODE 186
44
#define RUBY_RELEASE_CODE 20070923
5-
#define RUBY_PATCHLEVEL 109
5+
#define RUBY_PATCHLEVEL 110
66

77
#define RUBY_VERSION_MAJOR 1
88
#define RUBY_VERSION_MINOR 8

0 commit comments

Comments
 (0)