Skip to content

Commit

Permalink
* eval.c, intern.h, ext/thread/thread.c: should not free queue while
Browse files Browse the repository at this point in the history
	  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
  • Loading branch information
shyouhei committed Sep 23, 2007
1 parent 13d5a28 commit 50b224d
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 33 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
@@ -1,3 +1,8 @@
Sun Sep 23 07:49:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>

* eval.c, intern.h, ext/thread/thread.c: should not free queue while
any live threads are waiting. [ruby-dev:30653]

Sun Sep 23 06:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>

* ext/stringio/stringio.c (strio_init): separate from strio_initialize
Expand Down
1 change: 0 additions & 1 deletion eval.c
Expand Up @@ -6825,7 +6825,6 @@ rb_load(fname, wrap)
volatile VALUE self = ruby_top_self;
NODE *volatile last_node;
NODE *saved_cref = ruby_cref;
TMP_PROTECT;

if (wrap && ruby_safe_level >= 4) {
StringValue(fname);
Expand Down
50 changes: 19 additions & 31 deletions ext/thread/thread.c
Expand Up @@ -24,11 +24,12 @@ static VALUE rb_cSizedQueue;
static VALUE set_critical(VALUE value);

static VALUE
thread_exclusive_do(void)
thread_exclusive(VALUE (*func)(ANYARGS), VALUE arg)
{
rb_thread_critical = 1;
VALUE critical = rb_thread_critical;

return rb_yield(Qundef);
rb_thread_critical = 1;
return rb_ensure(func, arg, set_critical, (VALUE)critical);
}

/*
Expand All @@ -43,7 +44,7 @@ thread_exclusive_do(void)
static VALUE
rb_thread_exclusive(void)
{
return rb_ensure(thread_exclusive_do, Qundef, set_critical, rb_thread_critical);
return thread_exclusive(rb_yield, Qundef);
}

typedef struct _Entry {
Expand Down Expand Up @@ -147,7 +148,7 @@ shift_list(List *list)
VALUE value;

entry = list->entries;
if (!entry) return Qundef;
if (!entry) return Qnil;

list->entries = entry->next;
if (entry == list->last_entry) {
Expand Down Expand Up @@ -269,20 +270,12 @@ wait_list(List *list)
}

static void
assert_no_survivors(List *waiting, const char *label, void *addr)
kill_waiting_threads(List *waiting)
{
Entry *entry;
VALUE ths = 0;

for (entry = waiting->entries; entry; entry = entry->next) {
if (RTEST(wake_thread(entry->value))) {
if (!ths) ths = rb_ary_new();
rb_ary_push(ths, entry->value);
}
}
if (ths) {
rb_bug("%s %p freed with live thread(s) %s waiting",
label, addr, RSTRING_PTR(rb_inspect(ths)));
rb_thread_kill(entry->value);
}
}

Expand Down Expand Up @@ -334,7 +327,7 @@ finalize_mutex(Mutex *mutex)
static void
free_mutex(Mutex *mutex)
{
assert_no_survivors(&mutex->waiting, "mutex", mutex);
kill_waiting_threads(&mutex->waiting);
finalize_mutex(mutex);
xfree(mutex);
}
Expand Down Expand Up @@ -493,10 +486,8 @@ set_critical(VALUE value)
static VALUE
unlock_mutex(Mutex *mutex)
{
VALUE waking;
VALUE waking = thread_exclusive(unlock_mutex_inner, (VALUE)mutex);

rb_thread_critical = 1;
waking = rb_ensure(unlock_mutex_inner, (VALUE)mutex, set_critical, 0);
if (!RTEST(waking)) {
return Qfalse;
}
Expand Down Expand Up @@ -544,10 +535,9 @@ rb_mutex_exclusive_unlock(VALUE self)
VALUE waking;
Data_Get_Struct(self, Mutex, mutex);

rb_thread_critical = 1;
waking = rb_ensure(rb_mutex_exclusive_unlock_inner, (VALUE)mutex, set_critical, 0);
waking = thread_exclusive(rb_mutex_exclusive_unlock_inner, (VALUE)mutex);

if (waking == Qundef || !RTEST(waking)) {
if (!RTEST(waking)) {
return Qnil;
}

Expand Down Expand Up @@ -622,7 +612,7 @@ finalize_condvar(ConditionVariable *condvar)
static void
free_condvar(ConditionVariable *condvar)
{
assert_no_survivors(&condvar->waiting, "condition variable", condvar);
kill_waiting_threads(&condvar->waiting);
finalize_condvar(condvar);
xfree(condvar);
}
Expand Down Expand Up @@ -732,8 +722,7 @@ rb_condvar_broadcast(VALUE self)

Data_Get_Struct(self, ConditionVariable, condvar);

rb_thread_critical = 1;
rb_ensure(wake_all, (VALUE)&condvar->waiting, set_critical, 0);
thread_exclusive(wake_all, (VALUE)&condvar->waiting);
rb_thread_schedule();

return self;
Expand All @@ -750,9 +739,8 @@ rb_condvar_broadcast(VALUE self)
static void
signal_condvar(ConditionVariable *condvar)
{
VALUE waking;
rb_thread_critical = 1;
waking = rb_ensure(wake_one, (VALUE)&condvar->waiting, set_critical, 0);
VALUE waking = thread_exclusive(wake_one, (VALUE)&condvar->waiting);

if (RTEST(waking)) {
run_thread(waking);
}
Expand Down Expand Up @@ -827,9 +815,9 @@ finalize_queue(Queue *queue)
static void
free_queue(Queue *queue)
{
assert_no_survivors(&queue->mutex.waiting, "queue", queue);
assert_no_survivors(&queue->space_available.waiting, "queue", queue);
assert_no_survivors(&queue->value_available.waiting, "queue", queue);
kill_waiting_threads(&queue->mutex.waiting);
kill_waiting_threads(&queue->space_available.waiting);
kill_waiting_threads(&queue->value_available.waiting);
finalize_queue(queue);
xfree(queue);
}
Expand Down
2 changes: 1 addition & 1 deletion version.h
Expand Up @@ -2,7 +2,7 @@
#define RUBY_RELEASE_DATE "2007-09-23"
#define RUBY_VERSION_CODE 186
#define RUBY_RELEASE_CODE 20070923
#define RUBY_PATCHLEVEL 109
#define RUBY_PATCHLEVEL 110

#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
Expand Down

0 comments on commit 50b224d

Please sign in to comment.