rbczmq 1.7.4 → 1.7.5

Sign up to get free protection for your applications and to get access to all the features.
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
  }