zookeeper 1.0.2-java → 1.0.3-java
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -0
- data/Rakefile +1 -1
- data/ext/zookeeper_base.rb +25 -27
- data/ext/zookeeper_c.c +6 -0
- data/lib/zookeeper/version.rb +1 -1
- data/spec/forked_connection_spec.rb +4 -3
- metadata +3 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
v1.0.3 Linux: Fix hang on reopen after fork
|
2
|
+
|
3
|
+
* Linux users relying on fork() should upgrade to 1.0.3, as it
|
4
|
+
fixes a bug in the reopen code that would cause a hang in the child.
|
5
|
+
If you're running on linux, you *really* should upgrade
|
6
|
+
|
1
7
|
v1.0.0 Single Zookeeper namespace
|
2
8
|
|
3
9
|
* The top level Zookeeper class is now a module, the former Zookeeper
|
data/Rakefile
CHANGED
@@ -72,7 +72,7 @@ task :clobber do
|
|
72
72
|
end
|
73
73
|
|
74
74
|
# cargo culted from http://blog.flavorjon.es/2009/06/easily-valgrind-gdb-your-ruby-c.html
|
75
|
-
VALGRIND_BASIC_OPTS = '--num-callers=50 --error-limit=no --partial-loads-ok=yes --undef-value-errors=no'
|
75
|
+
VALGRIND_BASIC_OPTS = '--num-callers=50 --error-limit=no --partial-loads-ok=yes --undef-value-errors=no --trace-children=yes'
|
76
76
|
|
77
77
|
task 'valgrind' do
|
78
78
|
cd 'ext' do
|
data/ext/zookeeper_base.rb
CHANGED
@@ -72,6 +72,22 @@ class ZookeeperBase
|
|
72
72
|
threadsafe_inquisitor :connected?, :connecting?, :associating?, :running?
|
73
73
|
|
74
74
|
attr_reader :event_queue
|
75
|
+
|
76
|
+
# this method may be called in either the fork case, or from the constructor
|
77
|
+
# to set up this state initially (so all of this is in one location). we rely
|
78
|
+
# on the forked? method to determine which it is
|
79
|
+
def reopen_after_fork!
|
80
|
+
logger.debug { "#{self.class}##{__method__} fork detected!" } if forked?
|
81
|
+
|
82
|
+
@mutex = Monitor.new
|
83
|
+
@dispatch_shutdown_cond = @mutex.new_cond
|
84
|
+
@event_queue = QueueWithPipe.new
|
85
|
+
|
86
|
+
@dispatcher = nil if @dispatcher and not @dispatcher.alive?
|
87
|
+
|
88
|
+
update_pid! # from Forked
|
89
|
+
end
|
90
|
+
private :reopen_after_fork!
|
75
91
|
|
76
92
|
def reopen(timeout = 10, watcher=nil)
|
77
93
|
if watcher and (watcher != @default_watcher)
|
@@ -81,13 +97,16 @@ class ZookeeperBase
|
|
81
97
|
reopen_after_fork! if forked?
|
82
98
|
|
83
99
|
@mutex.synchronize do
|
100
|
+
if @czk
|
101
|
+
@czk.close
|
102
|
+
@czk = nil
|
103
|
+
end
|
104
|
+
|
105
|
+
@czk = CZookeeper.new(@host, @event_queue)
|
106
|
+
|
84
107
|
# flushes all outstanding watcher reqs.
|
85
108
|
@watcher_reqs.clear
|
86
109
|
set_default_global_watcher
|
87
|
-
|
88
|
-
orig_czk, @czk = @czk, CZookeeper.new(@host, @event_queue)
|
89
|
-
|
90
|
-
orig_czk.close if orig_czk
|
91
110
|
|
92
111
|
@czk.wait_until_connected(timeout)
|
93
112
|
end
|
@@ -100,15 +119,12 @@ class ZookeeperBase
|
|
100
119
|
@watcher_reqs = {}
|
101
120
|
@completion_reqs = {}
|
102
121
|
|
103
|
-
update_pid! # from Forked
|
104
|
-
|
105
122
|
@current_req_id = 0
|
106
123
|
|
107
|
-
|
124
|
+
@dispatcher = @czk = nil
|
125
|
+
|
108
126
|
reopen_after_fork!
|
109
127
|
|
110
|
-
@czk = nil
|
111
|
-
|
112
128
|
# approximate the java behavior of raising java.lang.IllegalArgumentException if the host
|
113
129
|
# argument ends with '/'
|
114
130
|
raise ArgumentError, "Host argument #{host.inspect} may not end with /" if host.end_with?('/')
|
@@ -202,24 +218,6 @@ class ZookeeperBase
|
|
202
218
|
end
|
203
219
|
|
204
220
|
protected
|
205
|
-
# this method may be called in either the fork case, or from the constructor
|
206
|
-
# to set up this state initially (so all of this is in one location). we rely
|
207
|
-
# on the forked? method to determine which it is
|
208
|
-
def reopen_after_fork!
|
209
|
-
logger.debug { "#{self.class}##{__method__}" }
|
210
|
-
@mutex = Monitor.new
|
211
|
-
@dispatch_shutdown_cond = @mutex.new_cond
|
212
|
-
@event_queue = QueueWithPipe.new
|
213
|
-
|
214
|
-
if @dispatcher and not @dispatcher.alive?
|
215
|
-
logger.debug { "#{self.class}##{__method__} re-starting dispatch thread" }
|
216
|
-
@dispatcher = nil
|
217
|
-
setup_dispatch_thread!
|
218
|
-
end
|
219
|
-
|
220
|
-
update_pid!
|
221
|
-
end
|
222
|
-
|
223
221
|
# this is a hack: to provide consistency between the C and Java drivers when
|
224
222
|
# using a chrooted connection, we wrap the callback in a block that will
|
225
223
|
# strip the chroot path from the returned path (important in an async create
|
data/ext/zookeeper_c.c
CHANGED
@@ -55,6 +55,8 @@ typedef enum {
|
|
55
55
|
static int destroy_zkrb_instance(struct zkrb_instance_data* ptr) {
|
56
56
|
int rv = ZOK;
|
57
57
|
|
58
|
+
zkrb_debug("destroy_zkrb_instance, zk_local_ctx: %p, zh: %p, queue: %p", ptr, ptr->zh, ptr->queue);
|
59
|
+
|
58
60
|
if (ptr->zh) {
|
59
61
|
const void *ctx = zoo_get_context(ptr->zh);
|
60
62
|
/* Note that after zookeeper_close() returns, ZK handle is invalid */
|
@@ -163,6 +165,7 @@ static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
|
|
163
165
|
VALUE data;
|
164
166
|
struct zkrb_instance_data *zk_local_ctx;
|
165
167
|
data = Data_Make_Struct(CZookeeper, struct zkrb_instance_data, 0, free_zkrb_instance_data, zk_local_ctx);
|
168
|
+
|
166
169
|
zk_local_ctx->queue = zkrb_queue_alloc();
|
167
170
|
|
168
171
|
if (zk_local_ctx->queue == NULL)
|
@@ -184,6 +187,9 @@ static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
|
|
184
187
|
ctx,
|
185
188
|
0);
|
186
189
|
|
190
|
+
zkrb_debug("method_zkrb_init, zk_local_ctx: %p, zh: %p, queue: %p, calling_ctx: %p",
|
191
|
+
zk_local_ctx, zk_local_ctx->zh, zk_local_ctx->queue, ctx);
|
192
|
+
|
187
193
|
#warning [wickman] TODO handle this properly on the Ruby side rather than C side
|
188
194
|
if (!zk_local_ctx->zh) {
|
189
195
|
rb_raise(rb_eRuntimeError, "error connecting to zookeeper: %d", errno);
|
data/lib/zookeeper/version.rb
CHANGED
@@ -17,8 +17,8 @@ unless defined?(::JRUBY_VERSION)
|
|
17
17
|
before do
|
18
18
|
if defined?(::Rubinius)
|
19
19
|
pending("this test is currently broken in rbx")
|
20
|
-
|
21
|
-
|
20
|
+
# elsif ENV['TRAVIS']
|
21
|
+
# pending("this test is currently hanging in travis")
|
22
22
|
else
|
23
23
|
@zk = Zookeeper.new(connection_string)
|
24
24
|
rm_rf(@zk, path)
|
@@ -54,6 +54,8 @@ unless defined?(::JRUBY_VERSION)
|
|
54
54
|
|
55
55
|
@zk.stat(:path => "#{pids_root}/child", :watcher => cb)
|
56
56
|
|
57
|
+
logger.debug { "-------------------> FORK <---------------------------" }
|
58
|
+
|
57
59
|
@pid = fork do
|
58
60
|
logger.debug { "reopening connection in child: #{$$}" }
|
59
61
|
@zk.reopen
|
@@ -69,7 +71,6 @@ unless defined?(::JRUBY_VERSION)
|
|
69
71
|
logger.debug { "waiting on child #{@pid}" }
|
70
72
|
|
71
73
|
@latch.await until @event
|
72
|
-
p @event
|
73
74
|
|
74
75
|
_, status = Process.wait2(@pid)
|
75
76
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zookeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 3
|
10
|
+
version: 1.0.3
|
11
11
|
platform: java
|
12
12
|
authors:
|
13
13
|
- Phillip Pearson
|