rbczmq 1.7.4 → 1.7.5

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.
Files changed (99) hide show
  1. checksums.yaml +5 -13
  2. data/.travis.yml +4 -1
  3. data/CHANGELOG.rdoc +13 -0
  4. data/Gemfile +8 -1
  5. data/Gemfile.lock +211 -2
  6. data/README.rdoc +7 -4
  7. data/ext/rbczmq/beacon.c +6 -3
  8. data/ext/rbczmq/context.c +117 -8
  9. data/ext/rbczmq/context.h +5 -0
  10. data/ext/rbczmq/message.c +6 -4
  11. data/ext/rbczmq/poller.c +12 -5
  12. data/ext/rbczmq/rbczmq_ext.c +2 -0
  13. data/ext/rbczmq/rbczmq_ext.h +1 -0
  14. data/ext/rbczmq/socket.c +135 -59
  15. data/ext/rbczmq/socket.h +2 -0
  16. data/ext/zeromq/CMakeLists.txt +3 -1
  17. data/ext/zeromq/NEWS +28 -3
  18. data/ext/zeromq/doc/zmq.txt +3 -3
  19. data/ext/zeromq/doc/zmq_getsockopt.txt +3 -3
  20. data/ext/zeromq/doc/zmq_msg_get.txt +2 -1
  21. data/ext/zeromq/doc/zmq_msg_more.txt +1 -1
  22. data/ext/zeromq/doc/zmq_setsockopt.txt +18 -19
  23. data/ext/zeromq/doc/zmq_socket.txt +4 -0
  24. data/ext/zeromq/include/zmq.h +14 -18
  25. data/ext/zeromq/src/clock.cpp +57 -2
  26. data/ext/zeromq/src/ctx.cpp +11 -5
  27. data/ext/zeromq/src/devpoll.cpp +5 -0
  28. data/ext/zeromq/src/devpoll.hpp +2 -0
  29. data/ext/zeromq/src/epoll.cpp +5 -0
  30. data/ext/zeromq/src/epoll.hpp +2 -0
  31. data/ext/zeromq/src/i_engine.hpp +2 -2
  32. data/ext/zeromq/src/kqueue.cpp +5 -0
  33. data/ext/zeromq/src/kqueue.hpp +2 -0
  34. data/ext/zeromq/src/pgm_receiver.cpp +2 -2
  35. data/ext/zeromq/src/pgm_receiver.hpp +2 -2
  36. data/ext/zeromq/src/pgm_sender.cpp +2 -2
  37. data/ext/zeromq/src/pgm_sender.hpp +2 -2
  38. data/ext/zeromq/src/poll.cpp +5 -0
  39. data/ext/zeromq/src/poll.hpp +2 -0
  40. data/ext/zeromq/src/router.cpp +2 -0
  41. data/ext/zeromq/src/select.cpp +5 -0
  42. data/ext/zeromq/src/select.hpp +2 -0
  43. data/ext/zeromq/src/session_base.cpp +2 -2
  44. data/ext/zeromq/src/signaler.cpp +73 -99
  45. data/ext/zeromq/src/signaler.hpp +2 -2
  46. data/ext/zeromq/src/socket_base.cpp +42 -40
  47. data/ext/zeromq/src/stream_engine.cpp +60 -58
  48. data/ext/zeromq/src/stream_engine.hpp +7 -8
  49. data/ext/zeromq/src/zmq_utils.cpp +6 -5
  50. data/ext/zeromq/tests/Makefile.am +6 -5
  51. data/ext/zeromq/tests/test_conflate.cpp +2 -5
  52. data/ext/zeromq/tests/test_ctx_destroy.cpp +1 -1
  53. data/ext/zeromq/tests/test_ctx_options.cpp +1 -1
  54. data/ext/zeromq/tests/test_immediate.cpp +1 -2
  55. data/ext/zeromq/tests/test_inproc_connect.cpp +1 -1
  56. data/ext/zeromq/tests/test_iov.cpp +1 -1
  57. data/ext/zeromq/tests/test_many_sockets.cpp +90 -0
  58. data/ext/zeromq/tests/test_monitor.cpp +3 -3
  59. data/ext/zeromq/tests/test_req_relaxed.cpp +1 -1
  60. data/ext/zeromq/tests/test_router_raw_empty.cpp +65 -0
  61. data/ext/zeromq/tests/test_spec_req.cpp +1 -1
  62. data/ext/zeromq/tests/test_stream.cpp +6 -7
  63. data/ext/zeromq/tests/test_sub_forward.cpp +1 -1
  64. data/ext/zeromq/tests/test_term_endpoint.cpp +2 -2
  65. data/ext/zeromq/tests/testutil.hpp +18 -1
  66. data/ext/zeromq/tools/Makefile.am +1 -1
  67. data/lib/zmq/socket.rb +1 -0
  68. data/lib/zmq/socket/stream.rb +44 -0
  69. data/lib/zmq/version.rb +1 -1
  70. data/test/socket/test_dealer_socket.rb +1 -1
  71. data/test/socket/test_pair_socket.rb +1 -1
  72. data/test/socket/test_pair_sockets.rb +1 -1
  73. data/test/socket/test_pub_socket.rb +1 -1
  74. data/test/socket/test_pub_sub_sockets.rb +1 -1
  75. data/test/socket/test_pull_socket.rb +1 -1
  76. data/test/socket/test_push_pull_sockets.rb +1 -1
  77. data/test/socket/test_push_socket.rb +1 -1
  78. data/test/socket/test_rep_socket.rb +1 -1
  79. data/test/socket/test_req_rep_sockets.rb +1 -1
  80. data/test/socket/test_req_socket.rb +1 -1
  81. data/test/socket/test_router_socket.rb +1 -1
  82. data/test/socket/test_routing.rb +1 -1
  83. data/test/socket/test_stream_socket.rb +74 -0
  84. data/test/socket/test_sub_socket.rb +1 -1
  85. data/test/test_beacon.rb +4 -2
  86. data/test/test_context.rb +2 -2
  87. data/test/test_frame.rb +2 -2
  88. data/test/test_handler.rb +2 -2
  89. data/test/test_logger.rb +1 -1
  90. data/test/test_loop.rb +2 -2
  91. data/test/test_message.rb +1 -1
  92. data/test/test_monitoring.rb +15 -3
  93. data/test/test_poller.rb +2 -2
  94. data/test/test_pollitem.rb +2 -2
  95. data/test/test_socket.rb +53 -6
  96. data/test/test_threading.rb +2 -2
  97. data/test/test_timer.rb +2 -2
  98. data/test/test_zmq.rb +2 -2
  99. metadata +109 -104
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OWI3ZDU3NzMwMTQ5NzEwYTY1MzkwYzA3NmQzYmY2YjE5YzI0NmM5MQ==
5
- data.tar.gz: !binary |-
6
- ZTlhN2Q2NzM1NzYxZjNlMjEzOWM3ZTVkNmYyM2FiMmQzYzE2NzIyYQ==
2
+ SHA1:
3
+ metadata.gz: 8ed671d96b6cc24a8815580b90a9fa972abc37ea
4
+ data.tar.gz: 9442f2bf13c7fd885656efabc7b46dc51ad0d1b6
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MzEzNjBiMTI2YmI3MGZkYjcyNjkzY2I1ODA2YWRhYzRjZGQ2ZTUzMzNkNzk4
10
- MmQzNWIxMTExOTkwNWU4NzI3ZjZkNmVlOTVjY2U0MDE4MWQzMTYxNDhjMmU4
11
- NjIyODg0ZGMxMjdjZWRmZjExOWMyZTA2OTAyNDY5ZTcyMmJkMDk=
12
- data.tar.gz: !binary |-
13
- Mzg3MDk5M2E1MjIwOGU3Yjg2NjlkMWZlMGNmYjM2NDE2NWQ5MTM2N2RhM2Y1
14
- NTJiMDNiMTUyNTk0ZGM2ODRmYjc0YTE0NTA1MmRhZGU2NDM3NzY2OTA0NDEx
15
- MGYxNTk1OGE1N2VmYzJhODdjNGE4MTFjMzRhMjBlZmNhMWJlYjg=
6
+ metadata.gz: 7b69981b46f42fa30476b3cb35036c24f0a33b7fa896b720fdda085fa4652fcb6a2107b936d9b94d2bab84b3bb02d3f16fcb044fe688a48389ad976acf429451
7
+ data.tar.gz: 53303923c66106bb2a17eea84c958b87106cf2d745af310bb19d30c2a3473b15acb5b6bbc7aa687fc0504ab8a858757241ce30ff31053b9b45c35d08397075e9
@@ -1,6 +1,7 @@
1
1
  language: ruby
2
+ bundler_args: --quiet
2
3
  rvm:
3
- - rbx-19mode
4
+ - rbx-2
4
5
  - 1.9.3
5
6
  - 2.0.0
6
7
  - ruby-head
@@ -14,6 +15,8 @@ notifications:
14
15
  branches:
15
16
  only:
16
17
  - master
18
+ before_install:
19
+ - if [[ $(ruby -v) =~ rubinius ]]; then travis_retry gem install rubysl; fi; gem list; true
17
20
  matrix:
18
21
  allow_failures:
19
22
  - rvm: ruby-head
@@ -1,5 +1,18 @@
1
1
  = Changelog
2
2
 
3
+ == 1.7.5 (January 17, 2014)
4
+
5
+ * Update to ZMQ 4.0.3. This fixes several bugs, incluing: https://github.com/zeromq/libzmq/issues/769
6
+ * Fix ZMQ::Poller#poll handling of signals (INT/TERM)
7
+ * Fix several cases where Ruby strings with NUL characters in them would have been truncated as C strings when sent in ZMQ messages.
8
+ * Updates Gemfile to support rubinius 2.
9
+ * Add ZMQ::Socket#unbind method. Has same affect as disconnect, but matches semantics of bind, as per other bindings.
10
+ * Update ZMQ::Socket state to only become disconnected after all connected/bound endpoints are removed with disconnect/unbind.
11
+ * Fix ZMQ::Socket connect/bind bug with percent symbols in the address URI.
12
+ * Add ZMQ::Socket#last_endpoint for retrieving the string URI with an ephemeral port number filled in.
13
+ * Add STREAM socket type, using ruby class ZMQ::Socket::Stream.
14
+ * Fix ZMQ::Socket implicit close when garbage collected.
15
+
3
16
  == 1.7.4 (November 25, 2013)
4
17
 
5
18
  * Update ZMQ::Socket to support strings with null bytes in them (Matt Connolly)
data/Gemfile CHANGED
@@ -3,4 +3,11 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'rake'
6
- gem 'rdoc'
6
+ gem 'rdoc'
7
+
8
+ # required for testing rubinius on travis:
9
+ platforms :rbx do
10
+ gem 'rubysl', '~> 2.0'
11
+ gem 'minitest', '~> 4.7'
12
+ gem 'rubysl-test-unit', '~> 2.0'
13
+ end
@@ -6,18 +6,227 @@ PATH
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ ffi2-generators (0.1.1)
9
10
  json (1.8.1)
10
- rake (10.1.0)
11
+ minitest (4.7.5)
12
+ rake (10.1.1)
11
13
  rake-compiler (0.8.3)
12
14
  rake
13
- rdoc (4.0.1)
15
+ rdoc (4.1.0)
14
16
  json (~> 1.4)
17
+ rubysl (2.0.15)
18
+ rubysl-abbrev (~> 2.0)
19
+ rubysl-base64 (~> 2.0)
20
+ rubysl-benchmark (~> 2.0)
21
+ rubysl-bigdecimal (~> 2.0)
22
+ rubysl-cgi (~> 2.0)
23
+ rubysl-cgi-session (~> 2.0)
24
+ rubysl-cmath (~> 2.0)
25
+ rubysl-complex (~> 2.0)
26
+ rubysl-continuation (~> 2.0)
27
+ rubysl-coverage (~> 2.0)
28
+ rubysl-csv (~> 2.0)
29
+ rubysl-curses (~> 2.0)
30
+ rubysl-date (~> 2.0)
31
+ rubysl-delegate (~> 2.0)
32
+ rubysl-digest (~> 2.0)
33
+ rubysl-drb (~> 2.0)
34
+ rubysl-e2mmap (~> 2.0)
35
+ rubysl-english (~> 2.0)
36
+ rubysl-enumerator (~> 2.0)
37
+ rubysl-erb (~> 2.0)
38
+ rubysl-etc (~> 2.0)
39
+ rubysl-expect (~> 2.0)
40
+ rubysl-fcntl (~> 2.0)
41
+ rubysl-fiber (~> 2.0)
42
+ rubysl-fileutils (~> 2.0)
43
+ rubysl-find (~> 2.0)
44
+ rubysl-forwardable (~> 2.0)
45
+ rubysl-getoptlong (~> 2.0)
46
+ rubysl-gserver (~> 2.0)
47
+ rubysl-io-console (~> 2.0)
48
+ rubysl-io-nonblock (~> 2.0)
49
+ rubysl-io-wait (~> 2.0)
50
+ rubysl-ipaddr (~> 2.0)
51
+ rubysl-irb (~> 2.0)
52
+ rubysl-logger (~> 2.0)
53
+ rubysl-mathn (~> 2.0)
54
+ rubysl-matrix (~> 2.0)
55
+ rubysl-mkmf (~> 2.0)
56
+ rubysl-monitor (~> 2.0)
57
+ rubysl-mutex_m (~> 2.0)
58
+ rubysl-net-ftp (~> 2.0)
59
+ rubysl-net-http (~> 2.0)
60
+ rubysl-net-imap (~> 2.0)
61
+ rubysl-net-pop (~> 2.0)
62
+ rubysl-net-protocol (~> 2.0)
63
+ rubysl-net-smtp (~> 2.0)
64
+ rubysl-net-telnet (~> 2.0)
65
+ rubysl-nkf (~> 2.0)
66
+ rubysl-observer (~> 2.0)
67
+ rubysl-open-uri (~> 2.0)
68
+ rubysl-open3 (~> 2.0)
69
+ rubysl-openssl (~> 2.0)
70
+ rubysl-optparse (~> 2.0)
71
+ rubysl-ostruct (~> 2.0)
72
+ rubysl-pathname (~> 2.0)
73
+ rubysl-prettyprint (~> 2.0)
74
+ rubysl-prime (~> 2.0)
75
+ rubysl-profile (~> 2.0)
76
+ rubysl-profiler (~> 2.0)
77
+ rubysl-pstore (~> 2.0)
78
+ rubysl-pty (~> 2.0)
79
+ rubysl-rational (~> 2.0)
80
+ rubysl-readline (~> 2.0)
81
+ rubysl-resolv (~> 2.0)
82
+ rubysl-rexml (~> 2.0)
83
+ rubysl-rinda (~> 2.0)
84
+ rubysl-rss (~> 2.0)
85
+ rubysl-scanf (~> 2.0)
86
+ rubysl-securerandom (~> 2.0)
87
+ rubysl-set (~> 2.0)
88
+ rubysl-shellwords (~> 2.0)
89
+ rubysl-singleton (~> 2.0)
90
+ rubysl-socket (~> 2.0)
91
+ rubysl-stringio (~> 2.0)
92
+ rubysl-strscan (~> 2.0)
93
+ rubysl-sync (~> 2.0)
94
+ rubysl-syslog (~> 2.0)
95
+ rubysl-tempfile (~> 2.0)
96
+ rubysl-thread (~> 2.0)
97
+ rubysl-thwait (~> 2.0)
98
+ rubysl-time (~> 2.0)
99
+ rubysl-timeout (~> 2.0)
100
+ rubysl-tmpdir (~> 2.0)
101
+ rubysl-tsort (~> 2.0)
102
+ rubysl-un (~> 2.0)
103
+ rubysl-uri (~> 2.0)
104
+ rubysl-weakref (~> 2.0)
105
+ rubysl-webrick (~> 2.0)
106
+ rubysl-xmlrpc (~> 2.0)
107
+ rubysl-yaml (~> 2.0)
108
+ rubysl-zlib (~> 2.0)
109
+ rubysl-abbrev (2.0.4)
110
+ rubysl-base64 (2.0.0)
111
+ rubysl-benchmark (2.0.1)
112
+ rubysl-bigdecimal (2.0.2)
113
+ rubysl-cgi (2.0.1)
114
+ rubysl-cgi-session (2.0.1)
115
+ rubysl-cmath (2.0.0)
116
+ rubysl-complex (2.0.0)
117
+ rubysl-continuation (2.0.0)
118
+ rubysl-coverage (2.0.3)
119
+ rubysl-csv (2.0.2)
120
+ rubysl-english (~> 2.0)
121
+ rubysl-curses (2.0.1)
122
+ rubysl-date (2.0.6)
123
+ rubysl-delegate (2.0.1)
124
+ rubysl-digest (2.0.3)
125
+ rubysl-drb (2.0.1)
126
+ rubysl-e2mmap (2.0.0)
127
+ rubysl-english (2.0.0)
128
+ rubysl-enumerator (2.0.0)
129
+ rubysl-erb (2.0.1)
130
+ rubysl-etc (2.0.3)
131
+ ffi2-generators (~> 0.1)
132
+ rubysl-expect (2.0.0)
133
+ rubysl-fcntl (2.0.4)
134
+ ffi2-generators (~> 0.1)
135
+ rubysl-fiber (2.0.0)
136
+ rubysl-fileutils (2.0.3)
137
+ rubysl-find (2.0.1)
138
+ rubysl-forwardable (2.0.1)
139
+ rubysl-getoptlong (2.0.0)
140
+ rubysl-gserver (2.0.0)
141
+ rubysl-socket (~> 2.0)
142
+ rubysl-thread (~> 2.0)
143
+ rubysl-io-console (2.0.0)
144
+ rubysl-io-nonblock (2.0.0)
145
+ rubysl-io-wait (2.0.0)
146
+ rubysl-ipaddr (2.0.0)
147
+ rubysl-irb (2.0.4)
148
+ rubysl-e2mmap (~> 2.0)
149
+ rubysl-mathn (~> 2.0)
150
+ rubysl-readline (~> 2.0)
151
+ rubysl-thread (~> 2.0)
152
+ rubysl-logger (2.0.0)
153
+ rubysl-mathn (2.0.0)
154
+ rubysl-matrix (2.1.0)
155
+ rubysl-e2mmap (~> 2.0)
156
+ rubysl-mkmf (2.0.1)
157
+ rubysl-fileutils (~> 2.0)
158
+ rubysl-shellwords (~> 2.0)
159
+ rubysl-monitor (2.0.0)
160
+ rubysl-mutex_m (2.0.0)
161
+ rubysl-net-ftp (2.0.1)
162
+ rubysl-net-http (2.0.4)
163
+ rubysl-cgi (~> 2.0)
164
+ rubysl-erb (~> 2.0)
165
+ rubysl-singleton (~> 2.0)
166
+ rubysl-net-imap (2.0.1)
167
+ rubysl-net-pop (2.0.1)
168
+ rubysl-net-protocol (2.0.1)
169
+ rubysl-net-smtp (2.0.1)
170
+ rubysl-net-telnet (2.0.0)
171
+ rubysl-nkf (2.0.1)
172
+ rubysl-observer (2.0.0)
173
+ rubysl-open-uri (2.0.0)
174
+ rubysl-open3 (2.0.0)
175
+ rubysl-openssl (2.0.5)
176
+ rubysl-optparse (2.0.1)
177
+ rubysl-shellwords (~> 2.0)
178
+ rubysl-ostruct (2.0.4)
179
+ rubysl-pathname (2.0.0)
180
+ rubysl-prettyprint (2.0.2)
181
+ rubysl-prime (2.0.1)
182
+ rubysl-profile (2.0.0)
183
+ rubysl-profiler (2.0.1)
184
+ rubysl-pstore (2.0.0)
185
+ rubysl-pty (2.0.2)
186
+ rubysl-rational (2.0.1)
187
+ rubysl-readline (2.0.2)
188
+ rubysl-resolv (2.0.0)
189
+ rubysl-rexml (2.0.2)
190
+ rubysl-rinda (2.0.0)
191
+ rubysl-rss (2.0.0)
192
+ rubysl-scanf (2.0.0)
193
+ rubysl-securerandom (2.0.0)
194
+ rubysl-set (2.0.1)
195
+ rubysl-shellwords (2.0.0)
196
+ rubysl-singleton (2.0.0)
197
+ rubysl-socket (2.0.1)
198
+ rubysl-stringio (2.0.0)
199
+ rubysl-strscan (2.0.0)
200
+ rubysl-sync (2.0.0)
201
+ rubysl-syslog (2.0.1)
202
+ ffi2-generators (~> 0.1)
203
+ rubysl-tempfile (2.0.1)
204
+ rubysl-test-unit (2.0.3)
205
+ minitest (~> 4.7)
206
+ rubysl-thread (2.0.2)
207
+ rubysl-thwait (2.0.0)
208
+ rubysl-time (2.0.3)
209
+ rubysl-timeout (2.0.0)
210
+ rubysl-tmpdir (2.0.0)
211
+ rubysl-tsort (2.0.1)
212
+ rubysl-un (2.0.0)
213
+ rubysl-fileutils (~> 2.0)
214
+ rubysl-optparse (~> 2.0)
215
+ rubysl-uri (2.0.0)
216
+ rubysl-weakref (2.0.0)
217
+ rubysl-webrick (2.0.0)
218
+ rubysl-xmlrpc (2.0.0)
219
+ rubysl-yaml (2.0.4)
220
+ rubysl-zlib (2.0.1)
15
221
 
16
222
  PLATFORMS
17
223
  ruby
18
224
 
19
225
  DEPENDENCIES
226
+ minitest (~> 4.7)
20
227
  rake
21
228
  rake-compiler (~> 0.8.0)
22
229
  rbczmq!
23
230
  rdoc
231
+ rubysl (~> 2.0)
232
+ rubysl-test-unit (~> 2.0)
@@ -1,6 +1,6 @@
1
1
  = rbczmq - binding for the high level ZeroMQ C API {<img src="https://secure.travis-ci.org/methodmissing/rbczmq.png" alt="Build Status" />}[http://travis-ci.org/methodmissing/rbczmq]
2
2
 
3
- (c) 2011-2013 Lourens Naudé (methodmissing), James Tucker (raggi), Matt Connolly (mattconnolly) with API guidance from the czmq (http://czmq.zeromq.org/) project.
3
+ (c) 2011-2014 Lourens Naudé (methodmissing), James Tucker (raggi), Matt Connolly (mattconnolly) with API guidance from the czmq (http://czmq.zeromq.org/) project.
4
4
 
5
5
  http://github.com/methodmissing/rbczmq
6
6
 
@@ -206,7 +206,7 @@ Here's a few basic examples. Please refer to documentation (http://methodmissing
206
206
  * A POSIX compliant OS, known to work well on Linux, BSD variants, Mac OS X and SmartOS.
207
207
  * Ruby MRI 1.9, 2.0 or Rubinius (JRuby capi support forthcoming)
208
208
  * A C compiler
209
- * This is a "fat" gem, including its own source code for both ZeroMQ and CZMQ libraries. No system installation if either library is required.
209
+ * This is a "fat" gem, including its own source code for both ZeroMQ and CZMQ libraries. No system installation of either library is required.
210
210
 
211
211
  == Installation
212
212
 
@@ -222,10 +222,14 @@ Building from source
222
222
  git submodule update
223
223
  rake
224
224
 
225
- Running tests
225
+ Running all tests
226
226
 
227
227
  rake test
228
228
 
229
+ Running a single test file:
230
+
231
+ ruby -Ilib test/test_context.rb
232
+
229
233
  OS X notes:
230
234
 
231
235
  If you are installing the package on a new Mac ensure you have libtool and autoconf installed.
@@ -247,7 +251,6 @@ This gem uses the "zmq" and "czmq" libraries, both of which are licensed under t
247
251
  * Revisit the ZMQ::Loop API
248
252
  * RDOC fail on mixed C and Ruby source files that document that same constants
249
253
  * GC guards to prevent recycling objects being sent / received.
250
- * Sockets can bind && connect to multiple endpoints - account for that
251
254
  * Watch out for further cases where REQ / REP pairs could raise EFSM
252
255
  * Do not clobber local scope from macros (James's commit in master)
253
256
  * Incorporate examples into CI as well
@@ -8,7 +8,10 @@
8
8
  static VALUE rb_czmq_nogvl_beacon_destroy(void *ptr)
9
9
  {
10
10
  zmq_beacon_wrapper *beacon = ptr;
11
- zbeacon_destroy(&beacon->beacon);
11
+ if (beacon->beacon) {
12
+ zbeacon_destroy(&beacon->beacon);
13
+ beacon->beacon = NULL;
14
+ }
12
15
  return Qnil;
13
16
  }
14
17
 
@@ -186,7 +189,7 @@ static VALUE rb_czmq_beacon_publish(VALUE obj, VALUE transmit)
186
189
  GetZmqBeacon(obj);
187
190
  Check_Type(transmit, T_STRING);
188
191
  args.beacon = beacon;
189
- args.transmit = StringValueCStr(transmit);
192
+ args.transmit = RSTRING_PTR(transmit);
190
193
  args.length = (int)RSTRING_LEN(transmit);
191
194
  rb_thread_blocking_region(rb_czmq_nogvl_publish, (void *)&args, RUBY_UBF_IO, 0);
192
195
  return Qnil;
@@ -254,7 +257,7 @@ static VALUE rb_czmq_beacon_subscribe(VALUE obj, VALUE filter)
254
257
  args.length = 0;
255
258
  } else {
256
259
  Check_Type(filter, T_STRING);
257
- args.filter = StringValueCStr(filter);
260
+ args.filter = RSTRING_PTR(filter);
258
261
  args.length = (int)RSTRING_LEN(filter);
259
262
  }
260
263
  rb_thread_blocking_region(rb_czmq_nogvl_subscribe, (void *)&args, RUBY_UBF_IO, 0);
@@ -1,6 +1,7 @@
1
1
  #include "rbczmq_ext.h"
2
2
 
3
3
  static VALUE intern_zctx_process;
4
+ static zmutex_t* context_mutex = NULL; /* this can only be used outside of Ruby GVL to avoid deadlocks */
4
5
 
5
6
  static VALUE rb_czmq_ctx_set_iothreads(VALUE context, VALUE io_threads);
6
7
 
@@ -18,13 +19,19 @@ static VALUE get_pid()
18
19
  */
19
20
  static VALUE rb_czmq_nogvl_zctx_destroy(void *ptr)
20
21
  {
22
+ zmutex_lock(context_mutex);
23
+
21
24
  errno = 0;
22
25
  zmq_ctx_wrapper *ctx = ptr;
23
26
  if (ctx->pid == getpid()) {
24
- /* only actually destroy the context if we are the process that created it. */
27
+ /* Only actually destroy the context if we are the process that created it. */
28
+ /* This may need to be changed when ZeroMQ's support for forking is improved. */
25
29
  zctx_destroy(&ctx->ctx);
26
30
  }
27
31
  ctx->flags |= ZMQ_CONTEXT_DESTROYED;
32
+
33
+ zmutex_unlock(context_mutex);
34
+
28
35
  return Qnil;
29
36
  }
30
37
 
@@ -37,9 +44,79 @@ static void rb_czmq_free_ctx(zmq_ctx_wrapper *ctx)
37
44
  {
38
45
  VALUE ctx_map;
39
46
  ctx_map = rb_ivar_get(rb_mZmq, intern_zctx_process);
47
+
48
+ // destroy sockets. This duplicates czmq's context shutdown which destroys sockets,
49
+ // but we need to process the list of Ruby ZMQ::Socket objects' data objects to mark
50
+ // them as closed so that they cannot be double destroyed.
51
+ zmq_sock_wrapper* socket;
52
+ while ((socket = zlist_pop(ctx->sockets))) {
53
+ rb_czmq_context_destroy_socket(socket);
54
+ }
55
+
56
+ // finally, shutdown the context.
40
57
  rb_thread_blocking_region(rb_czmq_nogvl_zctx_destroy, ctx, RUBY_UBF_IO, 0);
58
+
41
59
  ctx->ctx = NULL;
42
60
  rb_hash_aset(ctx_map, ctx->pidValue, Qnil);
61
+ zlist_destroy(&ctx->sockets);
62
+ }
63
+
64
+ /*
65
+ * :nodoc:
66
+ * Destroy the socket while the GIL is released - may block depending on socket linger value.
67
+ *
68
+ */
69
+ VALUE rb_czmq_nogvl_zsocket_destroy(void *ptr)
70
+ {
71
+ zmutex_lock(context_mutex);
72
+
73
+ zmq_sock_wrapper *sock = ptr;
74
+ errno = 0;
75
+ // zclock_log ("I: %s socket %p, context %p: destroy", zsocket_type_str(sock->socket), sock, sock->ctx);
76
+ zsocket_destroy(sock->ctx, sock->socket);
77
+
78
+ zmutex_unlock(context_mutex);
79
+ return Qnil;
80
+ }
81
+
82
+ /*
83
+ * :nodoc:
84
+ *
85
+ * Interal use: Close a socket from the context being destroyed or garbage collected, or
86
+ * from the socket being closed, or garbage collected.
87
+ *
88
+ * The order of these events cannot be determined, so this function has to be idempotent
89
+ * about this. The close socket call to CZMQ must happen only once or it will abort the
90
+ * application.
91
+ */
92
+ void rb_czmq_context_destroy_socket(zmq_sock_wrapper* socket)
93
+ {
94
+ if (socket == NULL || socket->context == NULL) {
95
+ return;
96
+ }
97
+
98
+ if (socket && socket->context == Qnil) {
99
+ // A socket with a context object of Qnil is created by ZMQ::Beacon#new.
100
+ // zbeacon is responsible for closing this socket in its own context, we will simply mark
101
+ // it as destroyed and let the ZMQ::Beacon object do the clean up when its internal
102
+ // context is destroyed.
103
+ }
104
+ else if (socket->ctx && socket->ctx_wrapper && !(socket->flags & ZMQ_SOCKET_DESTROYED)) {
105
+ zmq_ctx_wrapper *ctx = (zmq_ctx_wrapper *)socket->ctx_wrapper;
106
+ if (ctx) {
107
+ // remove from the list of socket objects created by this context object.
108
+ zlist_remove(ctx->sockets, socket);
109
+
110
+ if (socket->socket) {
111
+ rb_thread_blocking_region(rb_czmq_nogvl_zsocket_destroy, socket, RUBY_UBF_IO, 0);
112
+ }
113
+ }
114
+ }
115
+
116
+ socket->flags |= ZMQ_SOCKET_DESTROYED;
117
+ socket->ctx = NULL;
118
+ socket->socket = NULL;
119
+ socket->state = ZMQ_SOCKET_DISCONNECTED;
43
120
  }
44
121
 
45
122
  /*
@@ -56,6 +133,19 @@ static void rb_czmq_free_ctx_gc(void *ptr)
56
133
  }
57
134
  }
58
135
 
136
+ /*
137
+ * :nodoc:
138
+ * GC mark callback
139
+ *
140
+ */
141
+ static void rb_czmq_mark_ctx_gc(void *ptr)
142
+ {
143
+ zmq_ctx_wrapper *ctx = (zmq_ctx_wrapper *)ptr;
144
+ if (ctx) {
145
+ rb_gc_mark(ctx->pidValue);
146
+ }
147
+ }
148
+
59
149
  /*
60
150
  * :nodoc:
61
151
  * Creates a new context while the GIL is released.
@@ -67,6 +157,7 @@ static VALUE rb_czmq_nogvl_zctx_new(ZMQ_UNUSED void *ptr)
67
157
  zctx_t *ctx = NULL;
68
158
  ctx = zctx_new();
69
159
  zctx_set_linger(ctx, 1);
160
+ zsys_handler_reset(); // restore ruby signal handlers.
70
161
  return (VALUE)ctx;
71
162
  }
72
163
 
@@ -93,12 +184,13 @@ static VALUE rb_czmq_ctx_s_new(int argc, VALUE *argv, VALUE context)
93
184
  rb_scan_args(argc, argv, "01", &io_threads);
94
185
  ctx_map = rb_ivar_get(rb_mZmq, intern_zctx_process);
95
186
  if (!NIL_P(rb_hash_aref(ctx_map, get_pid()))) rb_raise(rb_eZmqError, "single ZMQ context per process allowed");
96
- context = Data_Make_Struct(rb_cZmqContext, zmq_ctx_wrapper, 0, rb_czmq_free_ctx_gc, ctx);
187
+ context = Data_Make_Struct(rb_cZmqContext, zmq_ctx_wrapper, rb_czmq_mark_ctx_gc, rb_czmq_free_ctx_gc, ctx);
97
188
  ctx->ctx = (zctx_t*)rb_thread_blocking_region(rb_czmq_nogvl_zctx_new, NULL, RUBY_UBF_IO, 0);
98
189
  ZmqAssertObjOnAlloc(ctx->ctx, ctx);
99
190
  ctx->flags = 0;
100
191
  ctx->pid = getpid();
101
192
  ctx->pidValue = get_pid();
193
+ ctx->sockets = zlist_new();
102
194
  rb_obj_call_init(context, 0, NULL);
103
195
  rb_hash_aset(ctx_map, ctx->pidValue, context);
104
196
  if (!NIL_P(io_threads)) rb_czmq_ctx_set_iothreads(context, io_threads);
@@ -189,7 +281,10 @@ VALUE rb_czmq_nogvl_socket_new(void *ptr)
189
281
  {
190
282
  errno = 0;
191
283
  struct nogvl_socket_args *args = ptr;
192
- return (VALUE)zsocket_new(args->ctx, args->type);
284
+ zmutex_lock(context_mutex);
285
+ VALUE result = (VALUE)zsocket_new(args->ctx, args->type);
286
+ zmutex_unlock(context_mutex);
287
+ return result;
193
288
  }
194
289
 
195
290
  /*
@@ -219,15 +314,17 @@ static inline VALUE rb_czmq_ctx_socket_klass(int socket_type)
219
314
  case ZMQ_DEALER: return rb_cZmqDealerSocket;
220
315
  break;
221
316
  case ZMQ_XPUB: return rb_cZmqXPubSocket;
222
- break;
317
+ break;
223
318
  case ZMQ_XSUB: return rb_cZmqXSubSocket;
224
- break;
319
+ break;
320
+ case ZMQ_STREAM: return rb_cZmqStreamSocket;
321
+ break;
225
322
  default: rb_raise(rb_eZmqError, "ZMQ socket type %d not supported!", socket_type);
226
323
  break;
227
324
  }
228
325
  }
229
326
 
230
- VALUE rb_czmq_socket_alloc(VALUE context, zctx_t *ctx, void *s)
327
+ VALUE rb_czmq_socket_alloc(VALUE context, zctx_t *zctx, void *s)
231
328
  {
232
329
  VALUE socket;
233
330
  zmq_sock_wrapper *sock = NULL;
@@ -235,7 +332,13 @@ VALUE rb_czmq_socket_alloc(VALUE context, zctx_t *ctx, void *s)
235
332
  sock->socket = s;
236
333
  ZmqAssertObjOnAlloc(sock->socket, sock);
237
334
  sock->flags = 0;
238
- sock->ctx = ctx;
335
+ sock->ctx = zctx; // czmq context
336
+ if (context == Qnil) {
337
+ sock->ctx_wrapper = NULL;
338
+ } else {
339
+ ZmqGetContext(context);
340
+ sock->ctx_wrapper = ctx; // rbczmq ZMQ::Context wrapped data struct
341
+ }
239
342
  sock->verbose = false;
240
343
  sock->state = ZMQ_SOCKET_PENDING;
241
344
  sock->endpoints = rb_ary_new();
@@ -276,7 +379,11 @@ static VALUE rb_czmq_ctx_socket(VALUE obj, VALUE type)
276
379
 
277
380
  args.ctx = ctx->ctx;
278
381
  args.type = socket_type;
279
- return rb_czmq_socket_alloc(obj, ctx->ctx, (void*)rb_thread_blocking_region(rb_czmq_nogvl_socket_new, (void *)&args, RUBY_UBF_IO, 0));
382
+ VALUE socket_object = rb_czmq_socket_alloc(obj, ctx->ctx, (void*)rb_thread_blocking_region(rb_czmq_nogvl_socket_new, (void *)&args, RUBY_UBF_IO, 0));
383
+ zmq_sock_wrapper *sock = NULL;
384
+ GetZmqSocket(socket_object);
385
+ zlist_push(ctx->sockets, sock);
386
+ return socket_object;
280
387
  }
281
388
 
282
389
  void _init_rb_czmq_context()
@@ -291,4 +398,6 @@ void _init_rb_czmq_context()
291
398
  rb_define_method(rb_cZmqContext, "iothreads=", rb_czmq_ctx_set_iothreads, 1);
292
399
  rb_define_method(rb_cZmqContext, "linger=", rb_czmq_ctx_set_linger, 1);
293
400
  rb_define_method(rb_cZmqContext, "socket", rb_czmq_ctx_socket, 1);
401
+
402
+ context_mutex = zmutex_new();
294
403
  }