zookeeper 1.0.2-java → 1.0.3-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|