[BUG] queue 0x424010 freed with live thread(s) waiting

e$B31$H$$$$$^$9!#e(B

e$B=PCY$l$F$7$^$$$^$7$?$,!"$d$C$He(Bsvne$BHG$r;n$7;O$a$^$7$?!#e(B

1.8e$B7O$N%V%i%s%A$Oe(Bruby_1_8e$B$G$h$$$N$G$7$?$C$1e(B?

e$B<!$N%9%/%j%W%H$N$h$&$Je(BQueuee$B$rBT$C$F$k%9%l%C%I$,$"$k>uBV$Ge(B
e$B%a%$%s%9%l%C%I$,=*N;$9$k%1!<%9$Ge(B
[BUG] queue 0x424010 freed with live thread(s) waiting
e$B$H$J$j$^$7$?!#e(B

e$B:F8=$7$?$N$O$3$NHG$G$9!#G[I[$5$l$F$$$ke(B1.8.6e$B$G$OLdBj$"$j$^$;$s!#e(B ruby 1.8.6 (2007-03-20 patchlevel 5000) [powerpc-darwin8.9.0]

-----lb.rb------

require ‘thread’

class LocalBarrier
def initialize(n)
@wait = Queue.new
@done = Queue.new
@keeper = begin_keeper(n)
end

def sync
@done.push(true)
@wait.pop
end

def join
@keeper.join
end

private
def begin_keeper(n)
Thread.start do
n.times do
@done.pop
end
n.times do
@wait.push(true)
end
end
end
end

n = 10

lb = LocalBarrier.new(n)

(n - 1).times do |i|
Thread.start do
sleep(rand(n) + 1)
puts “#{i}: done”
lb.sync
puts “#{i}: cont”
end
end

lb.sync
puts “#{n-1}: cone”

lb.join # <-- e$B$3$l$r%3%a%s%H%"%&%H$9$k$H:F8=$7$^$9!#e(B

puts “exit.”


svne$BHG$G$O<!$NDL$j<:GT$7$^$9!#e(B

four: mas$ ruby -dv lb.rb
ruby 1.8.6 (2007-03-20 patchlevel 5000) [powerpc-darwin8.9.0]
1: done
5: done
8: done
3: done
2: done
7: done
0: done
6: done
4: done
9: cone
exit.
lc.rb:50: [BUG] queue 0x424010 freed with live thread(s) waiting
ruby 1.8.6 (2007-03-20) [powerpc-darwin8.9.0]

Abort trap

e$BG[I[$5$l$F$$$ke(B1.8.6e$B$G$OLdBj$"$j$^$;$s!#e(B

four: mas$ ruby -dv lb.rb
ruby 1.8.6 (2007-03-13 patchlevel 0) [powerpc-darwin8.9.0]
1: done
7: done
6: done
8: done
0: done
4: done
3: done
2: done
5: done
9: cone
exit.

e$B$J$+$@$G$9!#e(B

At Tue, 20 Mar 2007 22:50:05 +0900,
Masatoshi SEKI wrote in [ruby-dev:30653]:

e$B=PCY$l$F$7$^$$$^$7$?$,!"$d$C$He(Bsvne$BHG$r;n$7;O$a$^$7$?!#e(B

e$B8+Mn$H$7$F$^$7$?!#e(B

e$B<!$N%9%/%j%W%H$N$h$&$Je(BQueuee$B$rBT$C$F$k%9%l%C%I$,$"$k>uBV$Ge(B
e$B%a%$%s%9%l%C%I$,=*N;$9$k%1!<%9$Ge(B
[BUG] queue 0x424010 freed with live thread(s) waiting
e$B$H$J$j$^$7$?!#e(B

r12068e$B$Ge(Bwait_condvar()e$B$,>o$Ke(Bmutexe$B$r:F%m%C%/$9$k$h$&$K$J$C$?$;$$e(B
e$B$N$h$&$G$9!#e(B

Index: eval.c

— eval.c (revision 12298)
+++ eval.c (working copy)
@@ -11214,8 +11214,17 @@ rb_thread_wakeup(thread)
VALUE thread;
{

  • if (!RTEST(rb_thread_wakeup_alive(thread)))
  • rb_raise(rb_eThreadError, “killed thread”);
  • return thread;
    +}

+VALUE
+rb_thread_wakeup_alive(thread)

  • VALUE thread;
    +{
    rb_thread_t th = rb_thread_check(thread);

    if (th->status == THREAD_KILLED)

  • rb_raise(rb_eThreadError, “killed thread”);
  • return Qnil;
    rb_thread_ready(th);

@@ -11292,5 +11301,5 @@ rb_thread_kill(thread)

 kill_thread(th, 0);
  • return thread;
  • return thread;
    }

@@ -11645,4 +11654,13 @@ rb_thread_abort_exc_set(thread, val)

+enum rb_thread_status
+rb_thread_status(thread)

  • VALUE thread;
    +{
  • rb_thread_t th = rb_thread_check(thread);
  • return th->status;
    +}

/*

  • call-seq:
    @@ -12121,5 +12139,5 @@ rb_thread_value(thread)

static VALUE
-rb_thread_status(thread)
+rb_thread_status_name(thread)
VALUE thread;
{
@@ -12982,5 +13000,5 @@ Init_Thread()
rb_define_method(rb_cThread, “exit!”, rb_thread_kill_bang, 0);
rb_define_method(rb_cThread, “value”, rb_thread_value, 0);

  • rb_define_method(rb_cThread, “status”, rb_thread_status, 0);
  • rb_define_method(rb_cThread, “status”, rb_thread_status_name, 0);
    rb_define_method(rb_cThread, “join”, rb_thread_join_m, -1);
    rb_define_method(rb_cThread, “alive?”, rb_thread_alive_p, 0);
    Index: intern.h
    ===================================================================
    — intern.h (revision 12298)
    +++ intern.h (working copy)
    @@ -205,6 +205,8 @@ void rb_thread_polling _((void));
    void rb_thread_sleep _((int));
    void rb_thread_sleep_forever _((void));
    +enum rb_thread_status rb_thread_status _((VALUE));
    VALUE rb_thread_stop _((void));
    VALUE rb_thread_wakeup _((VALUE));
    +VALUE rb_thread_wakeup_alive _((VALUE));
    VALUE rb_thread_run _((VALUE));
    VALUE rb_thread_kill _((VALUE));
    Index: ext/thread/thread.c
    ===================================================================
    — ext/thread/thread.c (revision 12298)
    +++ ext/thread/thread.c (working copy)
    @@ -13,4 +13,5 @@
    #include <intern.h>
    #include <rubysig.h>
    +#include <node.h>

static VALUE rb_cMutex;
@@ -208,6 +209,5 @@ static VALUE
wake_thread(VALUE thread)
{

  • return rb_rescue2(rb_thread_wakeup, thread,
  •  NULL, Qundef, rb_eThreadError, 0);
    
  • return rb_thread_wakeup_alive(thread);
    }

@@ -215,6 +215,8 @@ static VALUE
run_thread(VALUE thread)
{

  • return rb_rescue2(rb_thread_run, thread,
  •  NULL, Qundef, rb_eThreadError, 0);
    
  • thread = wake_thread(thread);
  • if (RTEST(thread) && !rb_thread_critical)
  • rb_thread_schedule();
  • return thread;
    }

@@ -226,5 +228,7 @@ wake_one(List *list)
waking = Qnil;
while (list->entries && !RTEST(waking)) {

  •    waking = wake_thread(shift_list(list));
    
  • waking = shift_list(list);
  • if (waking == Qundef) break;
  • waking = wake_thread(waking);
    }

@@ -267,8 +271,15 @@ assert_no_survivors(List *waiting, const
{
Entry *entry;

  • VALUE ths = 0;
  • for (entry = waiting->entries; entry; entry = entry->next) {
  •    if (RTEST(wake_thread(entry->value))) {
    
  •        rb_bug("%s %p freed with live thread(s) waiting", label, 
    

addr);

  •    }
    
  • 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)));
    
    }
    }
    @@ -404,9 +415,14 @@ lock_mutex(Mutex *mutex)
    rb_thread_critical = 1;
  • while (RTEST(mutex->owner)) {
  •    wait_list(&mutex->waiting);
    
  •    rb_thread_critical = 1;
    
  • if (!RTEST(mutex->owner)) {
  • mutex->owner = current;
  • }
  • else {
  • push_list(&mutex->waiting, current);
  • while (mutex->owner != current) {
  •  rb_thread_stop();
    
  •  rb_thread_critical = 1;
    
  • }
    }
  • mutex->owner = current;

    rb_thread_critical = 0;
    @@ -423,4 +439,20 @@ rb_mutex_lock(VALUE self)
    }

+static VALUE
+relock_mutex(Mutex *mutex)
+{

  • VALUE current = rb_thread_current();
  • switch (rb_thread_status(current)) {
  •  case THREAD_RUNNABLE:
    
  •  case THREAD_STOPPED:
    
  • lock_mutex(mutex);
  • break;
  •  default:
    
  • break;
  • }
  • return Qundef;
    +}

/*

  • Document-method: unlock
    @@ -443,6 +475,6 @@ unlock_mutex_inner(Mutex *mutex)
    }
  • mutex->owner = Qnil;
    waking = wake_one(&mutex->waiting);
  • mutex->owner = waking;

    return waking;
    @@ -463,12 +495,9 @@ unlock_mutex(Mutex *mutex)
    rb_thread_critical = 1;
    waking = rb_ensure(unlock_mutex_inner, (VALUE)mutex, set_critical,
    0);

  • if (waking == Qundef) {
  •    return Qfalse;
    
  • if (!RTEST(waking)) {
  • return Qfalse;
    }
  • if (RTEST(waking)) {
  •    run_thread(waking);
    
  • }
  • run_thread(waking);

    return Qtrue;
    @@ -516,11 +545,9 @@ rb_mutex_exclusive_unlock(VALUE self)
    waking = rb_ensure(rb_mutex_exclusive_unlock_inner, (VALUE)mutex,
    set_critical, 0);

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

    return self;
    @@ -634,11 +661,16 @@ static void
    wait_condvar(ConditionVariable *condvar, Mutex *mutex)
    {

  • VALUE waking;

  • rb_thread_critical = 1;
    if (rb_thread_current() != mutex->owner) {

  •    rb_thread_critical = 0;
    
  •    rb_raise(rb_eThreadError, "not owner of the synchronization 
    

mutex");

  • rb_thread_critical = 0;
  • rb_raise(rb_eThreadError, “not owner of the synchronization mutex”);
  • }
  • waking = unlock_mutex_inner(mutex);
  • if (RTEST(waking)) {
  • wake_thread(waking);
    }
  • unlock_mutex_inner(mutex);
  • rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex,
    (VALUE)mutex);
  • rb_ensure(wait_list, (VALUE)&condvar->waiting, relock_mutex,
    (VALUE)mutex);
    }

@@ -836,8 +868,8 @@ rb_queue_marshal_load(VALUE self, VALUE
array = rb_marshal_load(data);
if (TYPE(array) != T_ARRAY) {

  •    rb_raise(rb_eRuntimeError, "expected Array of queue data");
    
  • rb_raise(rb_eTypeError, “expected Array of queue data”);
    }
    if (RARRAY(array)->len < 1) {
  •    rb_raise(rb_eRuntimeError, "missing capacity value");
    
  • rb_raise(rb_eArgError, “missing capacity value”);
    }
    queue->capacity = NUM2ULONG(rb_ary_shift(array));

e$B$J$+$@$G$9!#e(B

At Wed, 23 May 2007 17:02:15 +0900,
Nobuyoshi N. wrote in [ruby-dev:30809]:

e$B<!$N%9%/%j%W%H$N$h$&$Je(BQueuee$B$rBT$C$F$k%9%l%C%I$,$"$k>uBV$Ge(B
e$B%a%$%s%9%l%C%I$,=*N;$9$k%1!<%9$Ge(B
[BUG] queue 0x424010 freed with live thread(s) waiting
e$B$H$J$j$^$7$?!#e(B

r12068e$B$Ge(Bwait_condvar()e$B$,>o$Ke(Bmutexe$B$r:F%m%C%/$9$k$h$&$K$J$C$?$;$$e(B
e$B$N$h$&$G$9!#e(B

[ruby-dev:30809]e$B$G$b!"%m%C%/$7$?$^$^e(Bforke$B$9$k$He(B[BUG]e$B$K$J$j$^$9!#e(B

Index: eval.c

— eval.c (revision 12390)
+++ eval.c (working copy)
@@ -11214,8 +11214,17 @@ rb_thread_wakeup(thread)
VALUE thread;
{

  • if (!RTEST(rb_thread_wakeup_alive(thread)))
  • rb_raise(rb_eThreadError, “killed thread”);
  • return thread;
    +}

+VALUE
+rb_thread_wakeup_alive(thread)

  • VALUE thread;
    +{
    rb_thread_t th = rb_thread_check(thread);

    if (th->status == THREAD_KILLED)

  • rb_raise(rb_eThreadError, “killed thread”);
  • return Qnil;
    rb_thread_ready(th);

@@ -11292,5 +11301,5 @@ rb_thread_kill(thread)

 kill_thread(th, 0);
  • return thread;
  • return thread;
    }

@@ -11645,4 +11654,13 @@ rb_thread_abort_exc_set(thread, val)

+enum rb_thread_status
+rb_thread_status(thread)

  • VALUE thread;
    +{
  • rb_thread_t th = rb_thread_check(thread);
  • return th->status;
    +}

/*

  • call-seq:
    @@ -12121,5 +12139,5 @@ rb_thread_value(thread)

static VALUE
-rb_thread_status(thread)
+rb_thread_status_name(thread)
VALUE thread;
{
@@ -12148,5 +12166,5 @@ rb_thread_status(thread)
*/

-static VALUE
+VALUE
rb_thread_alive_p(thread)
VALUE thread;
@@ -12982,5 +13000,5 @@ Init_Thread()
rb_define_method(rb_cThread, “exit!”, rb_thread_kill_bang, 0);
rb_define_method(rb_cThread, “value”, rb_thread_value, 0);

  • rb_define_method(rb_cThread, “status”, rb_thread_status, 0);
  • rb_define_method(rb_cThread, “status”, rb_thread_status_name, 0);
    rb_define_method(rb_cThread, “join”, rb_thread_join_m, -1);
    rb_define_method(rb_cThread, “alive?”, rb_thread_alive_p, 0);
    Index: intern.h
    ===================================================================
    — intern.h (revision 12390)
    +++ intern.h (working copy)
    @@ -205,8 +205,11 @@ void rb_thread_polling _((void));
    void rb_thread_sleep _((int));
    void rb_thread_sleep_forever _((void));
    +enum rb_thread_status rb_thread_status _((VALUE));
    VALUE rb_thread_stop _((void));
    VALUE rb_thread_wakeup _((VALUE));
    +VALUE rb_thread_wakeup_alive _((VALUE));
    VALUE rb_thread_run _((VALUE));
    VALUE rb_thread_kill _((VALUE));
    +VALUE rb_thread_alive_p _((VALUE));
    VALUE rb_thread_create _((VALUE ()(ANYARGS), void));
    void rb_thread_interrupt _((void));
    Index: ext/thread/thread.c
    ===================================================================
    — ext/thread/thread.c (revision 12390)
    +++ ext/thread/thread.c (working copy)
    @@ -13,4 +13,5 @@
    #include <intern.h>
    #include <rubysig.h>
    +#include <node.h>

static VALUE rb_cMutex;
@@ -208,6 +211,5 @@ static VALUE
wake_thread(VALUE thread)
{

  • return rb_rescue2(rb_thread_wakeup, thread,
  •  NULL, Qundef, rb_eThreadError, 0);
    
  • return rb_thread_wakeup_alive(thread);
    }

@@ -215,6 +217,8 @@ static VALUE
run_thread(VALUE thread)
{

  • return rb_rescue2(rb_thread_run, thread,
  •  NULL, Qundef, rb_eThreadError, 0);
    
  • thread = wake_thread(thread);
  • if (RTEST(thread) && !rb_thread_critical)
  • rb_thread_schedule();
  • return thread;
    }

@@ -226,5 +230,7 @@ wake_one(List *list)
waking = Qnil;
while (list->entries && !RTEST(waking)) {

  •    waking = wake_thread(shift_list(list));
    
  • waking = shift_list(list);
  • if (waking == Qundef) break;
  • waking = wake_thread(waking);
    }

@@ -267,8 +273,15 @@ assert_no_survivors(List *waiting, const
{
Entry *entry;

  • VALUE ths = 0;
  • for (entry = waiting->entries; entry; entry = entry->next) {
  •    if (RTEST(wake_thread(entry->value))) {
    
  •        rb_bug("%s %p freed with live thread(s) waiting", label, 
    

addr);

  •    }
    
  • 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)));
    
    }
    }
    @@ -304,4 +317,6 @@ typedef struct _Mutex {
    } Mutex;

+#define MUTEX_LOCKED_P(mutex) (RTEST((mutex)->owner) &&
rb_thread_alive_p((mutex)->owner))
+
static void
mark_mutex(Mutex *mutex)
@@ -362,5 +377,5 @@ rb_mutex_locked_p(VALUE self)
Mutex *mutex;
Data_Get_Struct(self, Mutex, mutex);

  • return RTEST(mutex->owner) ? Qtrue : Qfalse;
  • return MUTEX_LOCKED_P(mutex) ? Qtrue : Qfalse;
    }

@@ -381,5 +396,5 @@ rb_mutex_try_lock(VALUE self)
Data_Get_Struct(self, Mutex, mutex);

  • if (RTEST(mutex->owner))
  • if (MUTEX_LOCKED_P(mutex))
    return Qfalse;

@@ -404,9 +419,18 @@ lock_mutex(Mutex *mutex)
rb_thread_critical = 1;

  • while (RTEST(mutex->owner)) {
  •    wait_list(&mutex->waiting);
    
  •    rb_thread_critical = 1;
    
  • if (!MUTEX_LOCKED_P(mutex)) {
  • mutex->owner = current;
  • }
  • else {
  • push_list(&mutex->waiting, current);
  • do {
  •  rb_thread_stop();
    
  •  rb_thread_critical = 1;
    
  •  if (!MUTEX_LOCKED_P(mutex)) {
    
  • mutex->owner = current;
  • break;
  •  }
    
  • } while (mutex->owner != current);
    }
  • mutex->owner = current;

    rb_thread_critical = 0;
    @@ -423,4 +447,20 @@ rb_mutex_lock(VALUE self)
    }

+static VALUE
+relock_mutex(Mutex *mutex)
+{

  • VALUE current = rb_thread_current();
  • switch (rb_thread_status(current)) {
  •  case THREAD_RUNNABLE:
    
  •  case THREAD_STOPPED:
    
  • lock_mutex(mutex);
  • break;
  •  default:
    
  • break;
  • }
  • return Qundef;
    +}

/*

  • Document-method: unlock
    @@ -435,14 +475,10 @@ unlock_mutex_inner(Mutex *mutex)
    VALUE waking;
  • if (!RTEST(mutex->owner)) {

  • rb_raise(rb_eThreadError, “not owner”);

  • }

  • if (mutex->owner != rb_thread_current()) {
    rb_raise(rb_eThreadError, “not owner”);
    }

  • mutex->owner = Qnil;
    waking = wake_one(&mutex->waiting);

  • mutex->owner = waking;

    return waking;
    @@ -463,12 +499,9 @@ unlock_mutex(Mutex *mutex)
    rb_thread_critical = 1;
    waking = rb_ensure(unlock_mutex_inner, (VALUE)mutex, set_critical,
    0);

  • if (waking == Qundef) {
  • if (!RTEST(waking)) {
    return Qfalse;
    }
  • if (RTEST(waking)) {
  •    run_thread(waking);
    
  • }
  • run_thread(waking);

    return Qtrue;
    @@ -516,11 +550,9 @@ rb_mutex_exclusive_unlock(VALUE self)
    waking = rb_ensure(rb_mutex_exclusive_unlock_inner, (VALUE)mutex,
    set_critical, 0);

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

    return self;
    @@ -634,4 +666,6 @@ static void
    wait_condvar(ConditionVariable *condvar, Mutex *mutex)
    {

  • VALUE waking;

  • rb_thread_critical = 1;
    if (rb_thread_current() != mutex->owner) {
    @@ -639,6 +673,9 @@ wait_condvar(ConditionVariable *condvar,
    rb_raise(rb_eThreadError, “not owner of the synchronization
    mutex”);
    }

  • unlock_mutex_inner(mutex);
  • rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex,
    (VALUE)mutex);
  • waking = unlock_mutex_inner(mutex);
  • if (RTEST(waking)) {
  • wake_thread(waking);
  • }
  • rb_ensure(wait_list, (VALUE)&condvar->waiting, relock_mutex,
    (VALUE)mutex);
    }

@@ -836,8 +874,8 @@ rb_queue_marshal_load(VALUE self, VALUE
array = rb_marshal_load(data);
if (TYPE(array) != T_ARRAY) {

  •    rb_raise(rb_eRuntimeError, "expected Array of queue data");
    
  • rb_raise(rb_eTypeError, “expected Array of queue data”);
    }
    if (RARRAY(array)->len < 1) {
  •    rb_raise(rb_eRuntimeError, "missing capacity value");
    
  • rb_raise(rb_eArgError, “missing capacity value”);
    }
    queue->capacity = NUM2ULONG(rb_ary_shift(array));

e$B$J$+$@$G$9!#e(B

At Sat, 26 May 2007 01:44:25 +0900,
[email protected] wrote in [ruby-dev:30822]:

e$B<!$N%9%/%j%W%H$N$h$&$Je(BQueuee$B$rBT$C$F$k%9%l%C%I$,$"$k>uBV$Ge(B
e$B%a%$%s%9%l%C%I$,=*N;$9$k%1!<%9$Ge(B
[BUG] queue 0x424010 freed with live thread(s) waiting
e$B$H$J$j$^$7$?!#e(B

r12068e$B$Ge(Bwait_condvar()e$B$,>o$Ke(Bmutexe$B$r:F%m%C%/$9$k$h$&$K$J$C$?$;$$e(B
e$B$N$h$&$G$9!#e(B

[ruby-dev:30809]e$B$G$b!"%m%C%/$7$?$^$^e(Bforke$B$9$k$He(B[BUG]e$B$K$J$j$^$9!#e(B

1.8.6-p36e$B$K$Oe(B[ruby-dev:30822]e$B$8$c$J$/$Fe(B[ruby-dev:30809]e$B$,F~$C$Fe(B
e$B$$$^$9$,!":F8=%F%9%H$O$J$$$b$N$Ne(B[ruby-Bugs-11507]e$B$G%(%i!<$,5/$-e(B
e$B$k$H$$$&Js9p$,Mh$F$$$^$9!#e(B

e$B$H$j$"$($:e(Brelock_mutexe$B$O$?$7$+$K$^$:$=$&$J$N$G0J2<$N$h$&$J%Q%Ce(B
e$B%A$r=P$7$F$_$?$N$G$9$,!“e(B[ruby-dev:30653]e$B$KBP$9$k1F6A$,$h$/$o$+e(B
e$B$j$^$;$s!#:F8=$9$k$O$:$H;W$C$?$N$G$9$,!”<j85$G$O$J$<$+5/$-$^$;e(B
e$B$s$G$7$?!#$I$J$?$+3NG’$G$-$k$G$7$g$&$+!#e(B

Index: ext/thread/thread.c

— ext/thread/thread.c (revision 12567)
+++ ext/thread/thread.c (working copy)
@@ -13,7 +13,4 @@
#include <intern.h>
#include <rubysig.h>
-#include <node.h>

-enum rb_thread_status rb_thread_status _((VALUE));

static VALUE rb_cMutex;
@@ -263,8 +260,8 @@ wait_list_cleanup(List *list)
}

-static void
+static VALUE
wait_list(List *list)
{

  • rb_ensure(wait_list_inner, (VALUE)list, wait_list_cleanup,
    (VALUE)list);
  • return rb_ensure(wait_list_inner, (VALUE)list, wait_list_cleanup,
    (VALUE)list);
    }

@@ -447,20 +444,4 @@ rb_mutex_lock(VALUE self)
}

-static VALUE
-relock_mutex(Mutex *mutex)
-{

  • VALUE current = rb_thread_current();
  • switch (rb_thread_status(current)) {
  •  case THREAD_RUNNABLE:
    
  •  case THREAD_STOPPED:
    
  • lock_mutex(mutex);
  • break;
  •  default:
    
  • break;
  • }
  • return Qundef;
    -}

/*

  • Document-method: unlock
    @@ -676,5 +657,5 @@ wait_condvar(ConditionVariable *condvar,
    wake_thread(waking);
    }
  • rb_ensure(wait_list, (VALUE)&condvar->waiting, relock_mutex,
    (VALUE)mutex);
  • rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex,
    (VALUE)mutex);
    }