aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorngoto <ngoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-06-25 12:42:07 +0000
committerngoto <ngoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-06-25 12:42:07 +0000
commit401c4a465761b03a16fde23dec9bccc63f5146e4 (patch)
tree89b3058f989dc8e79b490b03d614efcac13a92fa
parent9289bcf9224dde71d771f5fc91cafba1f9393b2a (diff)
downloadruby-401c4a465761b03a16fde23dec9bccc63f5146e4.tar.gz
* test/-ext-/popen_deadlock/test_popen_deadlock.rb: test [Bug #11265]
* ext/-test-/popen_deadlock/infinite_loop_dlsym.c: new ext to call dlsym(3) infinitely without GVL, used in the above test. * ext/-test-/popen_deadlock/extconf.rb: extconf.rb for the above ext. Currently, only enabled on Solaris (main target) and Linux (as a reference platform and for debugging the ext). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog11
-rw-r--r--ext/-test-/popen_deadlock/extconf.rb4
-rw-r--r--ext/-test-/popen_deadlock/infinite_loop_dlsym.c50
-rw-r--r--test/-ext-/popen_deadlock/test_popen_deadlock.rb35
4 files changed, 100 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index fae0558719..dde7a756bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Thu Jun 25 21:24:28 2015 Naohisa Goto <ngotogenome@gmail.com>
+
+ * test/-ext-/popen_deadlock/test_popen_deadlock.rb: test [Bug #11265]
+
+ * ext/-test-/popen_deadlock/infinite_loop_dlsym.c: new ext to call
+ dlsym(3) infinitely without GVL, used in the above test.
+
+ * ext/-test-/popen_deadlock/extconf.rb: extconf.rb for the above
+ ext. Currently, only enabled on Solaris (main target) and Linux
+ (as a reference platform and for debugging the ext).
+
Thu Jun 25 19:24:25 2015 Naohisa Goto <ngotogenome@gmail.com>
* configure.in: not to use vfork on Solaris to avoid deadlock
diff --git a/ext/-test-/popen_deadlock/extconf.rb b/ext/-test-/popen_deadlock/extconf.rb
new file mode 100644
index 0000000000..f993ff7f9a
--- /dev/null
+++ b/ext/-test-/popen_deadlock/extconf.rb
@@ -0,0 +1,4 @@
+case RUBY_PLATFORM
+when /solaris/i, /linux/i
+ create_makefile("-test-/popen_deadlock/infinite_loop_dlsym")
+end
diff --git a/ext/-test-/popen_deadlock/infinite_loop_dlsym.c b/ext/-test-/popen_deadlock/infinite_loop_dlsym.c
new file mode 100644
index 0000000000..1d95a7cc9a
--- /dev/null
+++ b/ext/-test-/popen_deadlock/infinite_loop_dlsym.c
@@ -0,0 +1,50 @@
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include <dlfcn.h>
+
+struct data_for_loop_dlsym {
+ const char *name;
+ volatile int stop;
+};
+
+static void*
+native_loop_dlsym(void *data)
+{
+ struct data_for_loop_dlsym *s = data;
+
+ while (!(s->stop)) {
+ dlsym(RTLD_DEFAULT, s->name);
+ }
+
+ return NULL;
+}
+
+static void
+ubf_for_loop_dlsym(void *data)
+{
+ struct data_for_loop_dlsym *s = data;
+
+ s->stop = 1;
+
+ return;
+}
+
+static VALUE
+loop_dlsym(VALUE self, VALUE name)
+{
+ struct data_for_loop_dlsym d;
+
+ d.stop = 0;
+ d.name = StringValuePtr(name);
+
+ rb_thread_call_without_gvl(native_loop_dlsym, &d,
+ ubf_for_loop_dlsym, &d);
+
+ return self;
+}
+
+void
+Init_infinite_loop_dlsym(void)
+{
+ rb_define_method(rb_cThread, "__infinite_loop_dlsym__", loop_dlsym, 1);
+}
diff --git a/test/-ext-/popen_deadlock/test_popen_deadlock.rb b/test/-ext-/popen_deadlock/test_popen_deadlock.rb
new file mode 100644
index 0000000000..60ec6ccce4
--- /dev/null
+++ b/test/-ext-/popen_deadlock/test_popen_deadlock.rb
@@ -0,0 +1,35 @@
+begin
+ require '-test-/popen_deadlock/infinite_loop_dlsym'
+rescue LoadError
+ skip = true
+end
+
+class TestPopenDeadlock < Test::Unit::TestCase
+
+ # [Bug #11265]
+ def assert_popen_without_deadlock
+ assert_separately([], <<-"end;", timeout: 90) #do
+ require '-test-/popen_deadlock/infinite_loop_dlsym'
+
+ bug = '11265'.freeze
+ begin
+ t = Thread.new {
+ Thread.current.__infinite_loop_dlsym__("_ex_unwind")
+ }
+ str = IO.popen([ 'echo', bug ], 'r+') { |io| io.read }
+ assert_equal(bug, str.chomp)
+ ensure
+ t.kill if t
+ end
+ end;
+ end
+ private :assert_popen_without_deadlock
+
+ # 10 test methods are defined for showing progess reports
+ 10.times do |i|
+ define_method("test_popen_without_deadlock_#{i}") {
+ assert_popen_without_deadlock
+ }
+ end
+
+end unless skip #class TestPopenDeadlock