posix_mq 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +54 -0
- data/Documentation/posix-mq.rb.1.txt +7 -0
- data/GIT-VERSION-FILE +1 -1
- data/NEWS +10 -0
- data/README +39 -3
- data/ext/posix_mq/extconf.rb +3 -0
- data/ext/posix_mq/posix_mq.c +34 -13
- data/lib/posix_mq.rb +1 -1
- data/man/man1/posix-mq.rb.1 +9 -0
- data/test/test_posix_mq.rb +17 -1
- metadata +2 -2
data/ChangeLog
CHANGED
@@ -1,5 +1,59 @@
|
|
1
1
|
ChangeLog from git://git.bogomips.org/ruby_posix_mq.git ()
|
2
2
|
|
3
|
+
commit fd2fcdeee6b44f7854255cb7e01c81db3cd2d99c
|
4
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
5
|
+
Date: Sun Jan 3 05:46:45 2010 +0000
|
6
|
+
|
7
|
+
posix_mq 0.2.0
|
8
|
+
|
9
|
+
This release fixes notification (un)registration and should be
|
10
|
+
fully-supported on modern FreeBSD (7.2+) releases.
|
11
|
+
|
12
|
+
POSIX_MQ#notify=nil correctly unregister notification requests.
|
13
|
+
POSIX_MQ#notify=false now provids the no-op SIGEV_NONE
|
14
|
+
functionality. Under FreeBSD, using IO.select on POSIX_MQ
|
15
|
+
objects is now possible as it has always been under Linux.
|
16
|
+
|
17
|
+
commit 350bfc831938d84cc2d478f2cf88583863cb64fb
|
18
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
19
|
+
Date: Sun Jan 3 05:35:50 2010 +0000
|
20
|
+
|
21
|
+
support POSIX_MQ#to_io under FreeBSD
|
22
|
+
|
23
|
+
FreeBSD implements an __mq_oshandle(mqd_t mqd) function
|
24
|
+
to convert mqd_t to integer file descriptors.
|
25
|
+
|
26
|
+
commit 26015d39e9c848a536b4ea44802f858a4e6e74f7
|
27
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
28
|
+
Date: Sun Jan 3 04:17:56 2010 +0000
|
29
|
+
|
30
|
+
fix build under FreeBSD 7.2
|
31
|
+
|
32
|
+
FreeBSD seems to need some files explicitly included.
|
33
|
+
|
34
|
+
commit e7ac70686b3c09953f6c41966dbd77f77368a9ec
|
35
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
36
|
+
Date: Sat Jan 2 21:19:58 2010 -0800
|
37
|
+
|
38
|
+
doc: FreeBSD-specific notes + example code
|
39
|
+
|
40
|
+
commit 6f24b5626f89fbb6445c0943ba71f56c8945e18f
|
41
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
42
|
+
Date: Sat Jan 2 20:41:39 2010 -0800
|
43
|
+
|
44
|
+
Fix mq.notify = nil to unregister notifications
|
45
|
+
|
46
|
+
"mq.notify = false" also works now, doing what
|
47
|
+
"mq.notify = nil" used to do (using SIGEV_NONE).
|
48
|
+
|
49
|
+
I was confused by SIGEV_NONE usage vs using a NULL pointer for
|
50
|
+
the notification passed mq_notify(3). SIGEV_NONE does not
|
51
|
+
actually unregister, it registers a no-op notification which
|
52
|
+
prevents other processes from taking us.
|
53
|
+
|
54
|
+
This also fixes the test case to pass under both Linux and
|
55
|
+
FreeBSD.
|
56
|
+
|
3
57
|
commit 522d4d1472c216bd95a16ca5b118bc14693aad64
|
4
58
|
Author: Eric Wong <normalperson@yhbt.net>
|
5
59
|
Date: Sat Jan 2 02:33:23 2010 -0800
|
@@ -146,8 +146,15 @@ portability.
|
|
146
146
|
Exit status is normally 0. Exit status is 2 if a timeout occurs, 1 for
|
147
147
|
all other errors.
|
148
148
|
|
149
|
+
Under FreeBSD, the mq_* system calls are not available unless you load
|
150
|
+
the mqueuefs(5) kernel module:
|
151
|
+
|
152
|
+
kldload mqueuefs
|
153
|
+
|
149
154
|
# SEE ALSO
|
150
155
|
|
151
156
|
* [mq_overview(7)][1]
|
157
|
+
* [mqueuefs(5)][2]
|
152
158
|
|
153
159
|
[1]: http://kernel.org/doc/man-pages/online/pages/man7/mq_overview.7.html
|
160
|
+
[2]: http://freebsd.org/cgi/man.cgi?query=mqueuefs
|
data/GIT-VERSION-FILE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
GIT_VERSION = 0.
|
1
|
+
GIT_VERSION = 0.2.0
|
data/NEWS
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 0.2.0 / 2010-01-03 05:52 UTC
|
2
|
+
|
3
|
+
This release fixes notification (un)registration and should be
|
4
|
+
fully-supported on modern FreeBSD (7.2+) releases.
|
5
|
+
|
6
|
+
POSIX_MQ#notify=nil correctly unregister notification requests.
|
7
|
+
POSIX_MQ#notify=false now provids the no-op SIGEV_NONE
|
8
|
+
functionality. Under FreeBSD, using IO.select on POSIX_MQ
|
9
|
+
objects is now possible as it has always been under Linux.
|
10
|
+
|
1
11
|
=== 0.1.0 / 2010-01-02 11:01 UTC
|
2
12
|
|
3
13
|
initial
|
data/README
CHANGED
@@ -13,9 +13,9 @@ network-aware message queue implementations.
|
|
13
13
|
|
14
14
|
* Supports message notifications via signals.
|
15
15
|
|
16
|
-
* Supports portable non-blocking operation. Under Linux 2.6.6+
|
17
|
-
POSIX_MQ objects may even be used with event
|
18
|
-
such as IO.select.
|
16
|
+
* Supports portable non-blocking operation. Under Linux 2.6.6+ and
|
17
|
+
FreeBSD 7.2+, POSIX_MQ objects may even be used with event
|
18
|
+
notification mechanisms such as IO.select.
|
19
19
|
|
20
20
|
* Optional timeouts may be applied to send and receive operations.
|
21
21
|
|
@@ -42,6 +42,42 @@ Unpack it, and run "ruby setup.rb"
|
|
42
42
|
|
43
43
|
Otherwise, via RubyGems: gem install posix_mq
|
44
44
|
|
45
|
+
== Usage
|
46
|
+
|
47
|
+
The Linux mq_overview(7)
|
48
|
+
{manpage}[http://kernel.org/doc/man-pages/online/pages/man7/mq_overview.7.html]
|
49
|
+
provides a good overview of programming with POSIX message queues.
|
50
|
+
|
51
|
+
Under FreeBSD, you must load the
|
52
|
+
{mqueuefs(5)}[http://freebsd.org/cgi/man.cgi?query=mqueuefs]
|
53
|
+
kernel module before attempting to use POSIX message queues:
|
54
|
+
|
55
|
+
kldload mqueuefs
|
56
|
+
|
57
|
+
Our API matches the C api closely, see the RDoc for full API
|
58
|
+
documentation. Here is an example of a process communicating
|
59
|
+
with itself. In practice, processes that send will be different
|
60
|
+
from processes that receive.
|
61
|
+
|
62
|
+
require 'posix_mq'
|
63
|
+
mq = POSIX_MQ.new("/foo", :rw)
|
64
|
+
|
65
|
+
# hello world
|
66
|
+
mq << "hello world"
|
67
|
+
puts mq.receive.first # => should print "hello world"
|
68
|
+
|
69
|
+
# non-blocking operation
|
70
|
+
mq.nonblock = true
|
71
|
+
begin
|
72
|
+
mq.receive
|
73
|
+
rescue Errno::EAGAIN
|
74
|
+
end
|
75
|
+
|
76
|
+
trap(:USR1) { puts mq.receive.first }
|
77
|
+
mq.notify = :USR1
|
78
|
+
mq.send "fire USR1 handler"
|
79
|
+
# "fire USR1 handler" should be printed now
|
80
|
+
|
45
81
|
== Development
|
46
82
|
|
47
83
|
You can get the latest source via git from the following locations:
|
data/ext/posix_mq/extconf.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require "mkmf"
|
2
2
|
|
3
|
+
have_header("sys/select.h")
|
4
|
+
have_header("signal.h")
|
3
5
|
have_header("mqueue.h") or abort "mqueue.h header missing"
|
6
|
+
have_func("__mq_oshandle")
|
4
7
|
have_func("rb_str_set_len")
|
5
8
|
have_func("rb_struct_alloc_noinit")
|
6
9
|
have_func('rb_thread_blocking_region')
|
data/ext/posix_mq/posix_mq.c
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
#define _XOPEN_SOURCE 600
|
2
|
+
#ifdef HAVE_SYS_SELECT_H
|
3
|
+
# include <sys/select.h>
|
4
|
+
#endif
|
5
|
+
#ifdef HAVE_SIGNAL_H
|
6
|
+
# include <signal.h>
|
7
|
+
#endif
|
2
8
|
#include <ruby.h>
|
3
9
|
|
4
10
|
#include <time.h>
|
@@ -10,21 +16,25 @@
|
|
10
16
|
#include <unistd.h>
|
11
17
|
|
12
18
|
#if defined(__linux__)
|
13
|
-
# define
|
14
|
-
#
|
15
|
-
# define
|
19
|
+
# define MQD_TO_FD(mqd) (int)(mqd)
|
20
|
+
#elif defined(HAVE___MQ_OSHANDLE) /* FreeBSD */
|
21
|
+
# define MQD_TO_FD(mqd) __mq_oshandle(mqd)
|
16
22
|
#else
|
17
23
|
# warning mqd_t is not select()-able on your OS
|
18
|
-
# define MQD_IS_FD 0
|
19
24
|
# define MQ_IO_MARK(mq) ((void)(0))
|
20
25
|
# define MQ_IO_SET(mq,val) ((void)(0))
|
21
|
-
#endif
|
26
|
+
#endif
|
27
|
+
|
28
|
+
#ifdef MQD_TO_FD
|
29
|
+
# define MQ_IO_MARK(mq) rb_gc_mark((mq)->io)
|
30
|
+
# define MQ_IO_SET(mq,val) do { (mq)->io = (val); } while (0)
|
31
|
+
#endif
|
22
32
|
|
23
33
|
struct posix_mq {
|
24
34
|
mqd_t des;
|
25
35
|
long msgsize;
|
26
36
|
VALUE name;
|
27
|
-
#
|
37
|
+
#ifdef MQD_TO_FD
|
28
38
|
VALUE io;
|
29
39
|
#endif
|
30
40
|
};
|
@@ -463,7 +473,7 @@ static VALUE send0(VALUE self, VALUE buffer)
|
|
463
473
|
return self;
|
464
474
|
}
|
465
475
|
|
466
|
-
#
|
476
|
+
#ifdef MQD_TO_FD
|
467
477
|
/*
|
468
478
|
* call-seq:
|
469
479
|
* mq.to_io => IO
|
@@ -474,9 +484,10 @@ static VALUE send0(VALUE self, VALUE buffer)
|
|
474
484
|
static VALUE to_io(VALUE self)
|
475
485
|
{
|
476
486
|
struct posix_mq *mq = get(self, 1);
|
487
|
+
int fd = MQD_TO_FD(mq->des);
|
477
488
|
|
478
489
|
if (NIL_P(mq->io))
|
479
|
-
mq->io = rb_funcall(rb_cIO, id_new, 1, INT2NUM(
|
490
|
+
mq->io = rb_funcall(rb_cIO, id_new, 1, INT2NUM(fd));
|
480
491
|
|
481
492
|
return mq->io;
|
482
493
|
}
|
@@ -680,19 +691,32 @@ static int lookup_sig(VALUE sig)
|
|
680
691
|
* to the current process when message is received.
|
681
692
|
* If +signal+ is +nil+, it will unregister and disable the notification
|
682
693
|
* request to allow other processes to register a request.
|
694
|
+
* If +signal+ is +false+, it will register a no-op notification request
|
695
|
+
* which will prevent other processes from registering a notification.
|
683
696
|
* Only one process may have a notification request for a queue
|
684
697
|
* at a time, Errno::EBUSY will be raised if there is already
|
685
698
|
* a notification request registration for the queue.
|
699
|
+
*
|
700
|
+
* For readers of the mq_notify(3) manpage, passing +false+
|
701
|
+
* is equivalent to SIGEV_NONE, and passing +nil+ is equivalent
|
702
|
+
* of passing a NULL notification pointer to mq_notify(3).
|
686
703
|
*/
|
687
704
|
static VALUE setnotify(VALUE self, VALUE arg)
|
688
705
|
{
|
689
706
|
struct posix_mq *mq = get(self, 1);
|
690
707
|
struct sigevent not;
|
708
|
+
struct sigevent * notification = ¬
|
691
709
|
VALUE rv = arg;
|
692
710
|
|
693
711
|
not.sigev_notify = SIGEV_SIGNAL;
|
694
712
|
|
695
713
|
switch (TYPE(arg)) {
|
714
|
+
case T_FALSE:
|
715
|
+
not.sigev_notify = SIGEV_NONE;
|
716
|
+
break;
|
717
|
+
case T_NIL:
|
718
|
+
notification = NULL;
|
719
|
+
break;
|
696
720
|
case T_FIXNUM:
|
697
721
|
not.sigev_signo = NUM2INT(arg);
|
698
722
|
break;
|
@@ -701,15 +725,12 @@ static VALUE setnotify(VALUE self, VALUE arg)
|
|
701
725
|
not.sigev_signo = lookup_sig(arg);
|
702
726
|
rv = INT2NUM(not.sigev_signo);
|
703
727
|
break;
|
704
|
-
case T_NIL:
|
705
|
-
not.sigev_notify = SIGEV_NONE;
|
706
|
-
break;
|
707
728
|
default:
|
708
729
|
/* maybe support Proc+thread via sigev_notify_function.. */
|
709
730
|
rb_raise(rb_eArgError, "must be a signal or nil");
|
710
731
|
}
|
711
732
|
|
712
|
-
if (mq_notify(mq->des,
|
733
|
+
if (mq_notify(mq->des, notification) == MQD_INVALID)
|
713
734
|
rb_sys_fail("mq_notify");
|
714
735
|
|
715
736
|
return rv;
|
@@ -802,7 +823,7 @@ void Init_posix_mq_ext(void)
|
|
802
823
|
rb_define_method(cPOSIX_MQ, "notify=", setnotify, 1);
|
803
824
|
rb_define_method(cPOSIX_MQ, "nonblock=", setnonblock, 1);
|
804
825
|
rb_define_method(cPOSIX_MQ, "nonblock?", getnonblock, 0);
|
805
|
-
#
|
826
|
+
#ifdef MQD_TO_FD
|
806
827
|
rb_define_method(cPOSIX_MQ, "to_io", to_io, 0);
|
807
828
|
#endif
|
808
829
|
|
data/lib/posix_mq.rb
CHANGED
data/man/man1/posix-mq.rb.1
CHANGED
@@ -180,8 +180,17 @@ The value of MQUEUE should always be prefixed with a slash
|
|
180
180
|
.PP
|
181
181
|
Exit status is normally 0.
|
182
182
|
Exit status is 2 if a timeout occurs, 1 for all other errors.
|
183
|
+
.PP
|
184
|
+
Under FreeBSD, the mq_* system calls are not available unless you
|
185
|
+
load the mqueuefs(5) kernel module:
|
186
|
+
.PP
|
187
|
+
\f[CR]
|
188
|
+
\ \ \ \ kldload\ mqueuefs
|
189
|
+
\f[]
|
183
190
|
.SH SEE ALSO
|
184
191
|
.IP \[bu] 2
|
185
192
|
mq_overview(7) (http://kernel.org/doc/man-pages/online/pages/man7/mq_overview.7.html)
|
193
|
+
.IP \[bu] 2
|
194
|
+
mqueuefs(5) (http://freebsd.org/cgi/man.cgi?query=mqueuefs)
|
186
195
|
.SH AUTHOR
|
187
196
|
Ruby POSIX MQ hackers <ruby.posix.mq@librelist.com>
|
data/test/test_posix_mq.rb
CHANGED
@@ -136,11 +136,27 @@ class Test_POSIX_MQ < Test::Unit::TestCase
|
|
136
136
|
assert_nil(@mq.notify = nil)
|
137
137
|
assert_nothing_raised { @mq.send("hello", 0) }
|
138
138
|
assert_nil IO.select([rd], nil, nil, 0.1)
|
139
|
-
assert_raises(Errno::EBUSY) { @mq.notify = :USR1 }
|
140
139
|
ensure
|
141
140
|
trap(:USR1, orig)
|
142
141
|
end
|
143
142
|
|
143
|
+
def test_notify_none
|
144
|
+
@mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
|
145
|
+
assert_nothing_raised { @mq.notify = false }
|
146
|
+
pid = fork do
|
147
|
+
begin
|
148
|
+
@mq.notify = :USR1
|
149
|
+
rescue Errno::EBUSY
|
150
|
+
exit 0
|
151
|
+
rescue => e
|
152
|
+
p e
|
153
|
+
end
|
154
|
+
exit! 1
|
155
|
+
end
|
156
|
+
_, status = Process.waitpid2(pid)
|
157
|
+
assert status.success?, status.inspect
|
158
|
+
end
|
159
|
+
|
144
160
|
def test_setattr
|
145
161
|
@mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
|
146
162
|
mq_attr = POSIX_MQ::Attr.new(IO::NONBLOCK)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: posix_mq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ruby POSIX MQ hackers
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-03 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|