zookeeper 1.2.4-java → 1.2.5-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 +21 -0
- data/ext/c_zookeeper.rb +4 -6
- data/ext/extconf.rb +7 -0
- data/ext/zkrb.c +0 -9
- data/ext/zkrb_wrapper_compat.c +3 -3
- data/ext/zookeeper_base.rb +15 -9
- data/lib/zookeeper/continuation.rb +24 -3
- data/lib/zookeeper/exceptions.rb +4 -0
- data/lib/zookeeper/version.rb +1 -1
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
v1.2.5 cleanup locking in ZookeeperBase
|
2
|
+
|
3
|
+
* There were several situations where we would hold the lock before calling
|
4
|
+
a method on CZookeeper (inquisitors and #create in particular). This
|
5
|
+
exposed us to deadlocks in situations where an async event would be
|
6
|
+
delivered (probably a SESSION_EXPIRED event), but the callback block could
|
7
|
+
not be called because the dispatch thread would block on the mutex being
|
8
|
+
held by the caller of create.
|
9
|
+
|
10
|
+
This version cleans up that usage, and ensures that the only time we hold
|
11
|
+
the mutex is during startup/shutdown (when the value of @czk may be changing),
|
12
|
+
and in all other cases we grab the mutex, dereference, and unlock then perform
|
13
|
+
whatever action on the reference.
|
14
|
+
|
15
|
+
* Add a safety net to Continuation (which will soon be called 'Promise' or
|
16
|
+
'Future' at the request of @eric). If any operation takes more than 30s
|
17
|
+
an exception will be raised in the calling thread. The session timeout
|
18
|
+
setting makes it so that no operation should take more than 20s, so we know
|
19
|
+
if we haven't received a reply in *longer* than that, something has gone
|
20
|
+
awry.
|
21
|
+
|
1
22
|
v1.2.4 fix buffer overflow in CZookeeper client_id code
|
2
23
|
|
3
24
|
* the 'passwd' part of the struct is a char[16], but isn't null terminated.
|
data/ext/c_zookeeper.rb
CHANGED
@@ -176,6 +176,7 @@ class CZookeeper
|
|
176
176
|
return false unless wait_until_running(timeout)
|
177
177
|
|
178
178
|
@mutex.synchronize do
|
179
|
+
# TODO: use deadline here
|
179
180
|
@state_cond.wait(timeout) unless (@state == ZOO_CONNECTED_STATE)
|
180
181
|
end
|
181
182
|
|
@@ -191,15 +192,12 @@ class CZookeeper
|
|
191
192
|
end
|
192
193
|
|
193
194
|
cnt = Continuation.new(meth, *args)
|
194
|
-
@reg.
|
195
|
-
begin
|
195
|
+
@reg.synchronize do |r|
|
196
196
|
if meth == :state
|
197
|
-
|
197
|
+
r.state_check << cnt
|
198
198
|
else
|
199
|
-
|
199
|
+
r.pending << cnt
|
200
200
|
end
|
201
|
-
ensure
|
202
|
-
@reg.unlock rescue nil
|
203
201
|
end
|
204
202
|
wake_event_loop!
|
205
203
|
cnt.value
|
data/ext/extconf.rb
CHANGED
@@ -42,6 +42,11 @@ $LDFLAGS = "#{$libraries} #{$LDFLAGS}"
|
|
42
42
|
$LIBPATH = ["#{HERE}/lib"]
|
43
43
|
$DEFLIBPATH = []
|
44
44
|
|
45
|
+
# fix for rbenv?
|
46
|
+
if $LIBRUBYARG == ''
|
47
|
+
$LIBRUBYARG = RbConfig::CONFIG['LIBRUBYARG']
|
48
|
+
end
|
49
|
+
|
45
50
|
def safe_sh(cmd)
|
46
51
|
puts cmd
|
47
52
|
system(cmd)
|
@@ -87,6 +92,8 @@ Dir.chdir("#{HERE}/lib") do
|
|
87
92
|
end
|
88
93
|
$LIBS << " -lzookeeper_st_gem"
|
89
94
|
|
95
|
+
have_func('rb_thread_blocking_region')
|
96
|
+
|
90
97
|
$CFLAGS << ' -Wall' if ZK_DEV
|
91
98
|
create_makefile 'zookeeper_c'
|
92
99
|
|
data/ext/zkrb.c
CHANGED
@@ -824,7 +824,6 @@ static VALUE method_zkrb_iterate_event_loop(VALUE self) {
|
|
824
824
|
return INT2FIX(rc);
|
825
825
|
}
|
826
826
|
|
827
|
-
|
828
827
|
static VALUE method_has_events(VALUE self) {
|
829
828
|
VALUE rb_event;
|
830
829
|
FETCH_DATA_PTR(self, zk);
|
@@ -882,16 +881,8 @@ static VALUE method_recv_timeout(VALUE self) {
|
|
882
881
|
// returns a CZookeeper::ClientId object with the values set for session_id and passwd
|
883
882
|
static VALUE method_client_id(VALUE self) {
|
884
883
|
FETCH_DATA_PTR(self, zk);
|
885
|
-
char buf[32];
|
886
884
|
const clientid_t *cid = zoo_client_id(zk->zh);
|
887
885
|
|
888
|
-
/* if (strlen(cid->passwd) != 16) { */
|
889
|
-
/* zkrb_debug("passwd is not null-terminated");*/
|
890
|
-
/* } else {*/
|
891
|
-
/* hexbufify(buf, cid->passwd, 16);*/
|
892
|
-
/* zkrb_debug("password in hex is: %s", buf);*/
|
893
|
-
/* }*/
|
894
|
-
|
895
886
|
VALUE session_id = LL2NUM(cid->client_id);
|
896
887
|
VALUE passwd = rb_str_new(cid->passwd, 16);
|
897
888
|
|
data/ext/zkrb_wrapper_compat.c
CHANGED
@@ -4,10 +4,10 @@
|
|
4
4
|
|
5
5
|
VALUE zkrb_thread_blocking_region(zkrb_blocking_function_t *func, void *data1) {
|
6
6
|
|
7
|
-
#ifdef
|
8
|
-
return func(data1);
|
9
|
-
#else
|
7
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
10
8
|
return rb_thread_blocking_region((rb_blocking_function_t *)func, data1, RUBY_UBF_IO, 0);
|
9
|
+
#else
|
10
|
+
return func(data1);
|
11
11
|
#endif
|
12
12
|
|
13
13
|
}
|
data/ext/zookeeper_base.rb
CHANGED
@@ -31,17 +31,15 @@ class ZookeeperBase
|
|
31
31
|
ZOO_LOG_LEVEL_DEBUG = 4
|
32
32
|
|
33
33
|
|
34
|
-
def_delegators
|
34
|
+
def_delegators :czk, :get_children, :exists, :delete, :get, :set,
|
35
35
|
:set_acl, :get_acl, :client_id, :sync, :wait_until_connected
|
36
36
|
|
37
|
-
# some state methods need to be more paranoid about locking to ensure the correct
|
38
|
-
# state is returned
|
39
|
-
#
|
40
37
|
def self.threadsafe_inquisitor(*syms)
|
41
38
|
syms.each do |sym|
|
42
39
|
class_eval(<<-EOM, __FILE__, __LINE__+1)
|
43
40
|
def #{sym}
|
44
|
-
|
41
|
+
c = @mutex.synchronize { @czk }
|
42
|
+
false|(c && c.#{sym})
|
45
43
|
end
|
46
44
|
EOM
|
47
45
|
end
|
@@ -117,7 +115,7 @@ class ZookeeperBase
|
|
117
115
|
# if either of these happen, the user will need to renegotiate a connection via reopen
|
118
116
|
def assert_open
|
119
117
|
@mutex.synchronize do
|
120
|
-
raise Exceptions::NotConnected if closed?
|
118
|
+
raise Exceptions::NotConnected if !@czk or @czk.closed?
|
121
119
|
if forked?
|
122
120
|
raise InheritedConnectionError, <<-EOS.gsub(/(?:^|\n)\s*/, ' ').strip
|
123
121
|
You tried to use a connection inherited from another process
|
@@ -152,7 +150,7 @@ class ZookeeperBase
|
|
152
150
|
# is pretty damn annoying. this is used to clean things up.
|
153
151
|
def create(*args)
|
154
152
|
# since we don't care about the inputs, just glob args
|
155
|
-
rc, new_path =
|
153
|
+
rc, new_path = czk.create(*args)
|
156
154
|
[rc, strip_chroot_from(new_path)]
|
157
155
|
end
|
158
156
|
|
@@ -173,7 +171,7 @@ class ZookeeperBase
|
|
173
171
|
|
174
172
|
def state
|
175
173
|
return ZOO_CLOSED_STATE if closed?
|
176
|
-
|
174
|
+
czk.state
|
177
175
|
end
|
178
176
|
|
179
177
|
def session_id
|
@@ -190,7 +188,9 @@ class ZookeeperBase
|
|
190
188
|
|
191
189
|
# we are closed if there is no @czk instance or @czk.closed?
|
192
190
|
def closed?
|
193
|
-
|
191
|
+
czk.closed?
|
192
|
+
rescue Exceptions::NotConnected
|
193
|
+
true
|
194
194
|
end
|
195
195
|
|
196
196
|
def pause_before_fork_in_parent
|
@@ -243,6 +243,12 @@ protected
|
|
243
243
|
super(req_id, meth_name, call_opts)
|
244
244
|
end
|
245
245
|
|
246
|
+
def czk
|
247
|
+
rval = @mutex.synchronize { @czk }
|
248
|
+
raise Exceptions::NotConnected unless rval
|
249
|
+
rval
|
250
|
+
end
|
251
|
+
|
246
252
|
# if we're chrooted, this method will strip the chroot prefix from +path+
|
247
253
|
def strip_chroot_from(path)
|
248
254
|
return path unless (chrooted? and path and path.start_with?(chroot_path))
|
@@ -6,6 +6,8 @@ module Zookeeper
|
|
6
6
|
include Constants
|
7
7
|
include Logger
|
8
8
|
|
9
|
+
OPERATION_TIMEOUT = 30 # seconds
|
10
|
+
|
9
11
|
# for keeping track of which continuations are pending, and which ones have
|
10
12
|
# been submitted and are awaiting a repsonse
|
11
13
|
#
|
@@ -79,8 +81,8 @@ module Zookeeper
|
|
79
81
|
def initialize(meth, *args)
|
80
82
|
@meth = meth
|
81
83
|
@args = args
|
82
|
-
@mutex =
|
83
|
-
@cond =
|
84
|
+
@mutex = Monitor.new
|
85
|
+
@cond = @mutex.new_cond
|
84
86
|
@rval = nil
|
85
87
|
|
86
88
|
# make this error reporting more robust if necessary, right now, just set to state
|
@@ -88,9 +90,28 @@ module Zookeeper
|
|
88
90
|
end
|
89
91
|
|
90
92
|
# the caller calls this method and receives the response from the async loop
|
93
|
+
# this method has a hard-coded 30 second timeout as a safety feature. No
|
94
|
+
# call should take more than 20s (as the session timeout is set to 20s)
|
95
|
+
# so if any call takes longer than that, something has gone horribly wrong.
|
96
|
+
#
|
97
|
+
# @raise [ContinuationTimeoutError] if a response is not received within 30s
|
98
|
+
#
|
91
99
|
def value
|
100
|
+
time_to_stop = Time.now + OPERATION_TIMEOUT
|
101
|
+
now = nil
|
102
|
+
|
92
103
|
@mutex.synchronize do
|
93
|
-
|
104
|
+
while true
|
105
|
+
now = Time.now
|
106
|
+
break if @rval or @error or (now > time_to_stop)
|
107
|
+
|
108
|
+
deadline = time_to_stop.to_f - now.to_f
|
109
|
+
@cond.wait(deadline)
|
110
|
+
end
|
111
|
+
|
112
|
+
if now > time_to_stop
|
113
|
+
raise ContinuationTimeoutError, "response for meth: #{meth.inspect}, args: #{args.inspect}, not received within #{OPERATION_TIMEOUT} seconds"
|
114
|
+
end
|
94
115
|
|
95
116
|
case @error
|
96
117
|
when nil
|
data/lib/zookeeper/exceptions.rb
CHANGED
@@ -84,6 +84,10 @@ stacktrace:
|
|
84
84
|
# maybe use this for continuation
|
85
85
|
class InterruptedException < ZookeeperException ; end
|
86
86
|
|
87
|
+
# raised when a continuation operation takes more time than is reasonable and
|
88
|
+
# the thread should be awoken. (i.e. prevents a call that never returns)
|
89
|
+
class ContinuationTimeoutError < ZookeeperException; end
|
90
|
+
|
87
91
|
# raised when the user tries to use a connection after a fork()
|
88
92
|
# without calling reopen() in the C client
|
89
93
|
#
|
data/lib/zookeeper/version.rb
CHANGED
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: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 1.2.
|
9
|
+
- 5
|
10
|
+
version: 1.2.5
|
11
11
|
platform: java
|
12
12
|
authors:
|
13
13
|
- Phillip Pearson
|
@@ -20,7 +20,7 @@ autorequire:
|
|
20
20
|
bindir: bin
|
21
21
|
cert_chain: []
|
22
22
|
|
23
|
-
date: 2012-
|
23
|
+
date: 2012-06-03 00:00:00 Z
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: backports
|