Date | Commit message (Collapse) |
|
Apparently POSIX message queues adopted close-on-fork behavior
in FreeBSD at some point. Oh well, somebody else who is more
interested in FreeBSD than can look into fixing it on their end.
Improve exception reporting a bit while we're at it.
|
|
IO#close under Ruby 2.3 is idempotent, we shall follow suit
with POSIX_MQ#close
|
|
No changes for older Rubies, but this reduces garbage under 2.3
|
|
If a corresponding IO object exists or is created later, propagate
autoclose to the corresponding IO object to avoid simplify autoclose
handling for the user. This hopefully avoids nasty surprises in case
users disable autoclose but want to keep the IO object around.
|
|
These are analogous to the identically-named IO methods and useful
when we're inheriting descriptors (or writing tests for inheriting
descriptors).
|
|
DL is removed and deprecated, and we don't actually need
it or alarm to test for EINTR-safety.
|
|
This patch adds support for adopting an existing file descriptor, together
with testcases. The need for this comes up when we use systemd with the
ListenMessageQueue directive. For socket activation, systemd opens the POSIX
message queue and expects user code to begin using the file descriptor
without opening it in-process.
To support the systemd model in the `posix_mq` gem, this patch suggests
imitating the behavior on the Socket class, which uses `#for_fd` to create a
socket class from a descriptor.
One confounding factor exists. POSIX queues have a name but it is difficult
to get access to this name in a safe manner from the file descriptor. One
option would be to `readlink(2)` on `/proc/self/fd/N` to get the name[1], but
note that if the descriptor is unlinked we wouldn't get anything usable.
Rather than risk incorrect behavior and extra complexity, I've decided to
just raise an `ArgumentError` if `#name` is called on adopted descriptors.
Typically one wouldn't need the actual name in a systemd socket-activated
situation, anyway.
[1]: http://stackoverflow.com/questions/1188757/getting-filename-from-file-descriptor-in-c
[ew: simplified type checks to be consistent with IO.for_fd,
fixed test case]
Signed-off-by: Eric Wong <normalperson@yhbt.net>
|
|
On my i386-freebsd9 VM, this takes just longer than the
maximum allowable time.
|
|
|
|
Blocking functions should not raise Errno::EINTR to match
existing semantics of Ruby IO methods (e.g. IO.select, IO#read,
IO#write). This makes user code easier to read/write.
Like th Ruby methods we emulate, we only reacquire the GVL on
EINTR to fire signal handlers, but otherwise emulate SA_RESTART
semantics.
This is a backwards-incompatible API change (but unlikely
to break existing code).
|
|
Signed-off-by: Eric Wong <normalperson@yhbt.net>
|
|
The 3rd argument of DL::Function.new is ABI type, not a return type.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
|
|
This is to be consistent with POSIX_MQ#trysend
|
|
Cleaner code anyways.
|
|
These are kinder and less exceptional than their
non-trying counterparts as generating exceptions
is expensive for common EAGAIN errors.
|
|
It's only available when compiled with libffi.
|
|
These flags can be changed in the parent or child
process, so we will always have to run mq_getattr()
to check it. This removes the GVL-keeping non-blocking
optimizations but we'll gain some soon.
|
|
|
|
DL in Ruby 1.9 isn't the same
|
|
Some systems without mq_timedsend/mq_timedreceive need to
use alarm() or similar (setitimer()) to interrupt timed-out
mq_send/mq_receive calls, so we need to handle EINTR properly.
|
|
Not all systems can convert POSIX_MQ to IO objects.
|
|
Some ancient systems don't support mq_timedsend and
mq_timedreceive but somehow manage to support other POSIX
mq_* functions.
|
|
RSTRING_PTR may contain '\0' bytes which makes it unsuitable
for mq_unlink() and mq_open()
|
|
Cleaner code, too, no more direct RSTRUCT usage.
|
|
StringValuePtr should already be a sufficient guard.
There are more tests while we're at it, too, and we'll
now raise TypeError instead of ArgumentError when a
POSIX_MQ::Attr is not passed properly.
|
|
This function isn't exported in the standard Ruby headers,
it returns an aggregate value and isn't available in Rubinius,
either, so nuke it.
While we're at it, use clock_gettime() instead of gettimeofday()
to avoid unnecessary timeval usage since mq_send/mq_receive
rely on higher-precision timespecs instead.
|
|
I did not know about this method back in the day...
|
|
We shouldn't unnecessarily hog system resources.
|
|
It can be dangerous to hit (and ignore) EBADF errors in
multi-threaded applications. Users of POSIX_MQ#to_io have two
Ruby objects pointing to the same file descriptor, making
things tricky when it comes time to reap resources.
We'll always prefer to close the Ruby IO object if it exists
(because we have less control over its GC behavior) and
ignore the raw descriptor.
|
|
On ENOMEM, EMFILE, and ENFILE errors, it is customary to
invoke the Ruby GC and free up resources and retry the
system call.
|
|
tests for them were stupidly broken and never executed :x
|
|
We don't want folks to accidentally clobber the value for
others, so allocate a new string object for it (don't worry,
rb_str_dup() is cheap in 1.9).
|
|
It'll cause problems for the automatic mq_close() during GC
otherwise, as dup(2) on an mqd_t isn't portable.
Of course there's no point in cloning or duping, either, as
mq_send/mq_receive operations are always atomic at the kernel
level and only one thread can have a notification registered
for it.
|
|
|
|
This acts like POSIX_MQ#receive but only returns the message
without the priority.
|
|
SIGEV_THREAD is not easy to implement, so many platforms
do not implement it.
|
|
This is implementation uses both a short-lived POSIX thread and
a pre-spawned Ruby Thread in a manner that works properly under
both Ruby 1.8 (green threads) and 1.9 (where Ruby Threads are
POSIX threads).
The short-lived POSIX thread will write a single "\0" byte to
a pipe the Ruby Thread waits on. This operation is atomic
on all platforms. Once the Ruby Thread is woken up from the
pipe, it will execute th block given to it.
This dual-thread implementation is inspired by the way glibc
implements mq_notify(3) + SIGEV_THREAD under Linux where the
kernel itself cannot directly spawn POSIX threads.
|
|
"mq.notify = false" also works now, doing what
"mq.notify = nil" used to do (using SIGEV_NONE).
I was confused by SIGEV_NONE usage vs using a NULL pointer for
the notification passed mq_notify(3). SIGEV_NONE does not
actually unregister, it registers a no-op notification which
prevents other processes from taking us.
This also fixes the test case to pass under both Linux and
FreeBSD.
|
|
|