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 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
@@ -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
- # set up state that also needs to be re-setup after a fork()
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);
@@ -1,4 +1,4 @@
1
1
  module Zookeeper
2
- VERSION = '1.0.2'
2
+ VERSION = '1.0.3'
3
3
  DRIVER_VERSION = '3.3.5'
4
4
  end
@@ -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
- elsif ENV['TRAVIS']
21
- pending("this test is currently hanging in travis")
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: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 2
10
- version: 1.0.2
9
+ - 3
10
+ version: 1.0.3
11
11
  platform: java
12
12
  authors:
13
13
  - Phillip Pearson