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 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