mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* load.c (load_unlock): all threads requiring one file should
share same loading barrier, so it must be kept alive while those are waiting on it. [ruby-core:41618] [Bug #5754] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ddc15717cc
commit
ab6c8910f4
5 changed files with 79 additions and 3 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
Tue Dec 13 16:13:29 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* load.c (load_unlock): all threads requiring one file should
|
||||||
|
share same loading barrier, so it must be kept alive while those
|
||||||
|
are waiting on it. [ruby-core:41618] [Bug #5754]
|
||||||
|
|
||||||
Tue Dec 13 07:30:14 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
Tue Dec 13 07:30:14 2011 Aaron Patterson <aaron@tenderlovemaking.com>
|
||||||
|
|
||||||
* lib/webrick/httpresponse.rb (setup_header): 1xx responses
|
* lib/webrick/httpresponse.rb (setup_header): 1xx responses
|
||||||
|
|
|
@ -181,6 +181,7 @@ void rb_thread_execute_interrupts(VALUE th);
|
||||||
void rb_clear_trace_func(void);
|
void rb_clear_trace_func(void);
|
||||||
VALUE rb_thread_backtrace(VALUE thval);
|
VALUE rb_thread_backtrace(VALUE thval);
|
||||||
VALUE rb_get_coverages(void);
|
VALUE rb_get_coverages(void);
|
||||||
|
int rb_barrier_waiting(VALUE barrier);
|
||||||
|
|
||||||
/* thread_pthread.c, thread_win32.c */
|
/* thread_pthread.c, thread_win32.c */
|
||||||
void Init_native_thread(void);
|
void Init_native_thread(void);
|
||||||
|
|
8
load.c
8
load.c
|
@ -415,10 +415,12 @@ load_unlock(const char *ftptr, int done)
|
||||||
st_data_t key = (st_data_t)ftptr;
|
st_data_t key = (st_data_t)ftptr;
|
||||||
st_data_t data;
|
st_data_t data;
|
||||||
st_table *loading_tbl = get_loading_table();
|
st_table *loading_tbl = get_loading_table();
|
||||||
|
VALUE barrier;
|
||||||
|
|
||||||
if (st_delete(loading_tbl, &key, &data)) {
|
if (!st_lookup(loading_tbl, key, &data)) return;
|
||||||
VALUE barrier = (VALUE)data;
|
barrier = (VALUE)data;
|
||||||
xfree((char *)key);
|
if (rb_barrier_waiting(barrier) ||
|
||||||
|
(st_delete(loading_tbl, &key, &data) && (xfree((char *)key), 1))) {
|
||||||
if (done)
|
if (done)
|
||||||
rb_barrier_destroy(barrier);
|
rb_barrier_destroy(barrier);
|
||||||
else
|
else
|
||||||
|
|
|
@ -339,4 +339,60 @@ class TestRequire < Test::Unit::TestCase
|
||||||
[], /\$LOADED_FEATURES is frozen; cannot append feature \(RuntimeError\)$/,
|
[], /\$LOADED_FEATURES is frozen; cannot append feature \(RuntimeError\)$/,
|
||||||
bug3756)
|
bug3756)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_accessor :scratch
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_race_excption
|
||||||
|
bug5754 = '[ruby-core:41618]'
|
||||||
|
tmp = Tempfile.new(%w"bug5754 .rb")
|
||||||
|
path = tmp.path
|
||||||
|
tmp.print <<-EOS
|
||||||
|
TestRequire.scratch << :pre
|
||||||
|
Thread.pass until t2 = TestRequire.scratch[1]
|
||||||
|
Thread.pass until t2.stop?
|
||||||
|
open(__FILE__, "w") {|f| f.puts "TestRequire.scratch << :post"}
|
||||||
|
raise "con1"
|
||||||
|
EOS
|
||||||
|
tmp.close
|
||||||
|
|
||||||
|
start = false
|
||||||
|
fin = false
|
||||||
|
|
||||||
|
TestRequire.scratch = scratch = []
|
||||||
|
t1_res = nil
|
||||||
|
t2_res = nil
|
||||||
|
|
||||||
|
t1 = Thread.new do
|
||||||
|
begin
|
||||||
|
require(path)
|
||||||
|
rescue RuntimeError
|
||||||
|
end
|
||||||
|
|
||||||
|
t1_res = require(path)
|
||||||
|
|
||||||
|
Thread.pass until fin
|
||||||
|
scratch << :t1
|
||||||
|
end
|
||||||
|
|
||||||
|
t2 = Thread.new do
|
||||||
|
Thread.pass until scratch[0]
|
||||||
|
begin
|
||||||
|
scratch << t2
|
||||||
|
t2_res = require(path)
|
||||||
|
scratch << :t2
|
||||||
|
ensure
|
||||||
|
fin = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_nothing_raised(ThreadError, bug5754) {t1.join}
|
||||||
|
assert_nothing_raised(ThreadError, bug5754) {t2.join}
|
||||||
|
|
||||||
|
assert_equal([false, true], [t1_res, t2_res], bug5754)
|
||||||
|
assert_equal([:pre, t2, :post, :t2, :t1], scratch, bug5754)
|
||||||
|
|
||||||
|
tmp.close(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
11
thread.c
11
thread.c
|
@ -3723,6 +3723,17 @@ rb_barrier_destroy(VALUE self)
|
||||||
return rb_mutex_unlock(mutex);
|
return rb_mutex_unlock(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_barrier_waiting(VALUE self)
|
||||||
|
{
|
||||||
|
VALUE mutex = GetBarrierPtr(self);
|
||||||
|
rb_mutex_t *m;
|
||||||
|
|
||||||
|
if (!mutex) return 0;
|
||||||
|
GetMutexPtr(mutex, m);
|
||||||
|
return m->cond_waiting;
|
||||||
|
}
|
||||||
|
|
||||||
/* variables for recursive traversals */
|
/* variables for recursive traversals */
|
||||||
static ID recursive_key;
|
static ID recursive_key;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue