Feature #15350 ยป 0001-thread_sync.c-queue_sleep-remove-deadlock-checking.patch
| test/ruby/test_thread_queue.rb | ||
|---|---|---|
|
puts q.pop
|
||
|
puts 'exit'
|
||
|
INPUT
|
||
|
skip 'fork not present' unless Process.respond_to?(:fork)
|
||
|
assert_separately([], <<-INPUT)
|
||
|
q = Queue.new
|
||
|
trap(:CHLD) { q.push :CHLD }
|
||
|
pid = fork { exit!(0) }
|
||
|
q.pop
|
||
|
pid, st = Process.waitpid2(pid)
|
||
|
assert_predicate st, :success?
|
||
|
INPUT
|
||
|
end
|
||
|
def test_fork_while_queue_waiting
|
||
| thread_sync.c | ||
|---|---|---|
|
return queue_do_push(self, queue_ptr(self), obj);
|
||
|
}
|
||
|
static VALUE
|
||
|
queue_sleep(VALUE arg)
|
||
|
{
|
||
|
rb_thread_sleep_deadly_allow_spurious_wakeup();
|
||
|
return Qnil;
|
||
|
}
|
||
|
struct queue_waiter {
|
||
|
struct sync_waiter w;
|
||
|
union {
|
||
| ... | ... | |
|
} as;
|
||
|
};
|
||
|
static VALUE
|
||
|
queue_sleep(VALUE p)
|
||
|
{
|
||
|
struct queue_waiter *qw = (struct queue_waiter *)p;
|
||
|
sleep_forever(qw->w.th, 0);
|
||
|
return Qnil;
|
||
|
}
|
||
|
static VALUE
|
||
|
queue_sleep_done(VALUE p)
|
||
|
{
|
||
| ... | ... | |
|
list_add_tail(&qw.as.q->waitq, &qw.w.node);
|
||
|
qw.as.q->num_waiting++;
|
||
|
rb_ensure(queue_sleep, self, queue_sleep_done, (VALUE)&qw);
|
||
|
rb_ensure(queue_sleep, (VALUE)&qw, queue_sleep_done, (VALUE)&qw);
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
list_add_tail(pushq, &qw.w.node);
|
||
|
sq->num_waiting_push++;
|
||
|
rb_ensure(queue_sleep, self, szqueue_sleep_done, (VALUE)&qw);
|
||
|
rb_ensure(queue_sleep, (VALUE)&qw, szqueue_sleep_done, (VALUE)&qw);
|
||
|
}
|
||
|
}
|
||
|
-
|
||