0mq 0.5.1 → 0.5.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b804860f9ff37973173ff9061a18674bfebfdc1d
4
- data.tar.gz: fb5c958be97696bed9da3faa6c04bc7362377234
3
+ metadata.gz: 136e40f0d38d2aa86916cc8134140819f3b6153d
4
+ data.tar.gz: b9dc4d0d931e3069dcd6f72705d23276e5b96fd5
5
5
  SHA512:
6
- metadata.gz: 16dbace3339b1acf206c4f9cdcb33bedb8a92291748feec4c6a437b55a3595245aa6ba12502f8e39ddf4416ffd543288a4e164ad47ed56960e2e48da117acd1c
7
- data.tar.gz: 31357bb71a7f4f43525f328ee87a195472d6d4f1d22f1391f44b456043cb4e3841353f7922b5a7d75e8a22fe0e6c7e19ea59932a482b8f0596ac9449095c212e
6
+ metadata.gz: 6e78f5d97aac700192c295c5c246e310154c1a259d7f9e478552bcadf62daec60aee60994c8bba0cd8430fd872a7cd6f8de9bd73f577d7058fe0557b67198069
7
+ data.tar.gz: fedd23a1ff754f4e94da1388990633dea10b1b87b48951189093d3b801e5d4d24dfd6ce051c7330a10d1e77f4b536099fc87048ff3b01a4d3fe1cbf3ba3ef3d0
data/lib/0mq.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'ffi-rzmq-core'
2
2
 
3
- require_relative '0mq/error_map'
3
+ require_relative '0mq/error_check'
4
4
 
5
5
  require_relative '0mq/context'
6
6
  require_relative '0mq/socket'
@@ -9,21 +9,70 @@ module ZMQ
9
9
  attr_reader :pointer
10
10
 
11
11
  def initialize
12
+ # FFI socket pointer for this context
12
13
  @pointer = LibZMQ.zmq_ctx_new
14
+
15
+ # List of FFI socket pointers associated with this context.
16
+ # Each Socket is responsible for registering and unregistering
17
+ # its pointer from the Context it is associated with.
18
+ # See #register_socket_pointer and #unregister_socket_pointer,
19
+ # as well as #terminate and self.finalizer (where they get closed)
20
+ @socket_pointers = Array.new
21
+ @socket_pointers_mutex = Mutex.new
22
+
23
+ ObjectSpace.define_finalizer self,
24
+ self.class.finalizer(@pointer, @socket_pointers, Process.pid)
25
+ end
26
+
27
+ # @api private
28
+ def register_socket_pointer pointer
29
+ @socket_pointers_mutex.synchronize do
30
+ @socket_pointers.push pointer
31
+ end
32
+ end
33
+
34
+ # @api private
35
+ def unregister_socket_pointer pointer
36
+ @socket_pointers_mutex.synchronize do
37
+ @socket_pointers.delete pointer
38
+ end
13
39
  end
14
40
 
15
41
  # Destroy the ØMQ context.
16
42
  def terminate
17
43
  if @pointer
18
- rc = LibZMQ.version4? ?
19
- LibZMQ.zmq_ctx_term(@pointer) :
20
- LibZMQ.zmq_term(@pointer)
21
- ZMQ.error_check true if rc == -1
44
+ ObjectSpace.undefine_finalizer self
45
+
46
+ rc = LibZMQ.respond_to?(:zmq_ctx_term) ?
47
+ LibZMQ.zmq_ctx_term(pointer) :
48
+ LibZMQ.zmq_term(pointer)
49
+ ZMQ.error_check true if rc==-1
22
50
 
23
51
  @pointer = nil
24
52
  end
25
53
  end
26
54
 
55
+ # Create a safe finalizer for the context pointer to terminate on GC
56
+ def self.finalizer(pointer, socket_pointers, pid)
57
+ Proc.new do
58
+ if Process.pid == pid
59
+ # Close all socket pointers associated with this context.
60
+ #
61
+ # If any of these sockets are still open when zmq_ctx_term is called,
62
+ # the call will hang. This is problematic, as the execution of
63
+ # finalizers is not multithreaded, and the order of finalizers is not
64
+ # guaranteed. Even when the Sockets each hold a reference to the
65
+ # Context, the Context could still be GCed first, causing lockup.
66
+ socket_pointers.each { |ptr| LibZMQ.zmq_close ptr }
67
+ socket_pointers.clear
68
+
69
+ LibZMQ.respond_to?(:zmq_ctx_term) ?
70
+ LibZMQ.zmq_ctx_term(pointer) :
71
+ LibZMQ.zmq_term(pointer)
72
+ end
73
+ end
74
+ end
75
+
27
76
  # Create a Socket within this context.
28
77
  def socket(type, opts={})
29
78
  opts[:context] = self
@@ -3,12 +3,12 @@ module ZMQ
3
3
 
4
4
  # A hash of error number => exception class.
5
5
  # Example: 1 => Errno::EPERM
6
- ErrorMap = Hash.new
6
+ @error_map = Hash.new
7
7
 
8
8
  Errno.constants
9
9
  .map { |x| Errno.const_get x }
10
10
  .select { |x| x.is_a?(Class) && x < SystemCallError }
11
- .each { |x| ErrorMap[x.const_get(:Errno)] = x }
11
+ .each { |x| @error_map[x.const_get(:Errno)] = x }
12
12
 
13
13
 
14
14
  # Checks the libzmq global error number and raises it as an exception.
@@ -16,11 +16,14 @@ module ZMQ
16
16
  # Example: ZMQ.error_check if rc == -1
17
17
  def self.error_check(adjust_backtrace=false)
18
18
  errno = LibZMQ.zmq_errno
19
- return true if errno == 25
19
+ return true if errno == 25 # TODO: What is this for? Remove?
20
20
 
21
- # TODO: Use adjust_backtrace
22
- str = ''
23
- raise ErrorMap[errno], str, caller[0...-2]
21
+ backtrace = adjust_backtrace ? caller[0...-2] : caller
22
+ if @error_map.has_key? errno
23
+ raise @error_map[errno], '', backtrace
24
+ else
25
+ raise SystemCallError, errno.to_s, backtrace
26
+ end
24
27
  end
25
28
 
26
29
  end
@@ -106,7 +106,5 @@ module ZMQ
106
106
  @dead
107
107
  end
108
108
 
109
- # TODO: add finalizer for cleanup for neglectful user developers
110
-
111
109
  end
112
110
  end
@@ -23,8 +23,10 @@ module ZMQ
23
23
 
24
24
  @msgptr = FFI::MemoryPointer.new LibZMQ::Message.size, 1, false
25
25
 
26
+ @context.send :register_socket_pointer, @pointer
27
+
26
28
  ObjectSpace.define_finalizer self,
27
- self.class.finalizer(@socket, Process.pid)
29
+ self.class.finalizer(@pointer, @context, Process.pid)
28
30
  end
29
31
 
30
32
  # Show a useful inspect output
@@ -37,13 +39,16 @@ module ZMQ
37
39
  @closed = true
38
40
 
39
41
  if @pointer
40
- ObjectSpace.undefine_finalizer self
41
42
  @temp_buffers.clear if @temp_buffers
42
43
 
44
+ ObjectSpace.undefine_finalizer self
45
+ @context.send :unregister_socket_pointer, @pointer
46
+
43
47
  rc = LibZMQ.zmq_close @pointer
44
48
  ZMQ.error_check true if rc==-1
45
49
 
46
50
  @pointer = nil
51
+ @context = nil
47
52
  end
48
53
  end
49
54
 
@@ -52,9 +57,14 @@ module ZMQ
52
57
  @closed
53
58
  end
54
59
 
55
- # Create a safe finalizer for the socket pointer to close on GC of the object
56
- def self.finalizer(pointer, pid)
57
- Proc.new { LibZMQ.zmq_close pointer if Process.pid == pid }
60
+ # Create a safe finalizer for the socket pointer to close on GC
61
+ def self.finalizer(pointer, context, pid)
62
+ Proc.new do
63
+ if Process.pid == pid
64
+ context.send :unregister_socket_pointer, pointer
65
+ LibZMQ.zmq_close pointer
66
+ end
67
+ end
58
68
  end
59
69
 
60
70
  # Get the socket type name as a symbol
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: 0mq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-08 00:00:00.000000000 Z
12
+ date: 2014-06-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi-rzmq-core
@@ -134,7 +134,7 @@ files:
134
134
  - lib/0mq.rb
135
135
  - lib/0mq/context.rb
136
136
  - lib/0mq/curve.rb
137
- - lib/0mq/error_map.rb
137
+ - lib/0mq/error_check.rb
138
138
  - lib/0mq/poll.rb
139
139
  - lib/0mq/poll_interruptible.rb
140
140
  - lib/0mq/proxy.rb