IPC via named pipe: Difference between revisions
Content added Content deleted
m (omissions) |
(Add Ruby {{in progress}}.) |
||
Line 8: | Line 8: | ||
* Your program may assume it's the sole reader on "in" and the sole writer on "out". |
* Your program may assume it's the sole reader on "in" and the sole writer on "out". |
||
* Read/write operation on pipes are generally blocking. Make your program responsive to both pipes, so that it won't block trying to read the "in" pipe while leaving another process hanging on the other end of "out" pipe indefinitely -- or vice versa. You probably need to either poll the pipes or use multi-threading. |
* Read/write operation on pipes are generally blocking. Make your program responsive to both pipes, so that it won't block trying to read the "in" pipe while leaving another process hanging on the other end of "out" pipe indefinitely -- or vice versa. You probably need to either poll the pipes or use multi-threading. |
||
==={{header|Ruby}}=== |
|||
{{in progress|lang=Ruby|day=30|month=September|year=2011}} |
|||
With [[OpenBSD]], we observe that open(2) a named pipe blocks ''all threads'' in a process. (This must be bug in thread library.) So, we fork(2) other process to call open(2), and apply UNIXSocket to send IO object. |
|||
<lang ruby>require 'socket' |
|||
# Ruby has no direct access to mkfifo(2). We use a shell script. |
|||
system 'sh', '-c', <<EOF or abort |
|||
test -p in || mkfifo in || exit |
|||
test -p out || mkfifo out || exit |
|||
EOF |
|||
# Forks a process to open _path_. Returns a _socket_ to receive the open |
|||
# IO object (by UNIXSocket#recv_io), and the _pid_ of the process. |
|||
def open_sesame(path, mode) |
|||
reader, writer = UNIXSocket.pair |
|||
pid = fork do |
|||
begin |
|||
reader.close |
|||
file = File.open(path, mode) |
|||
writer.send_io file |
|||
ensure |
|||
exit! |
|||
end |
|||
end |
|||
writer.close |
|||
return reader, pid |
|||
end |
|||
insock, inpid = open_sesame("in", "rb") |
|||
outsock, outpid = open_sesame("out", "w") |
|||
Process.detach(inpid) |
|||
Process.detach(outpid) |
|||
inpipe, outpipe = nil |
|||
count = 0 |
|||
readers = [insock, outsock] |
|||
writers = [] |
|||
loop do |
|||
selection = select(readers, writers) |
|||
selection[0].each do |reader| |
|||
case reader |
|||
when insock |
|||
inpipe = reader.recv_io |
|||
when outsock |
|||
outpipe = reader.recv_io |
|||
when inpipe |
|||
count += (inpipe.read_nonblock.size rescue 0) |
|||
end |
|||
end |
|||
selection[1].each do |writer| |
|||
case writer |
|||
when outpipe |
|||
outpipe.puts count |
|||
exit |
|||
end |
|||
end |
|||
end</lang> |
|||
<pre>$ ruby count.rb |
|||
count.rb:39:in `recv_io': file descriptor was not passed (msg_controllen=0 smaller than sizeof(struct cmsghdr)=12) (SocketError) |
|||
from count.rb:39:in `block (2 levels) in <main>' |
|||
from count.rb:36:in `each' |
|||
from count.rb:36:in `block in <main>' |
|||
from count.rb:34:in `loop' |
|||
from count.rb:34:in `<main>'</pre> |
|||
{{omit from|GUISS}} |
{{omit from|GUISS}} |