Detect when reader closes named pipe (FIFO)
Oddly enough, it appears that when the last reader closes the pipe, select
indicates that the pipe is readable:
writer.py
#!/usr/bin/env python
import os
import select
import time
NAME = 'fifo2'
os.mkfifo(NAME)
def select_test(fd, r=True, w=True, x=True):
rset = [fd] if r else []
wset = [fd] if w else []
xset = [fd] if x else []
t0 = time.time()
r,w,x = select.select(rset, wset, xset)
print 'After {0} sec:'.format(time.time() - t0)
if fd in r: print ' {0} is readable'.format(fd)
if fd in w: print ' {0} is writable'.format(fd)
if fd in x: print ' {0} is exceptional'.format(fd)
try:
fd = os.open(NAME, os.O_WRONLY)
print '{0} opened for writing'.format(NAME)
print 'select 1'
select_test(fd)
os.write(fd, 'test')
print 'wrote data'
print 'select 2'
select_test(fd)
print 'select 3 (no write)'
select_test(fd, w=False)
finally:
os.unlink(NAME)
Demo:
Terminal 1:
$ ./pipe_example_simple.py
fifo2 opened for writing
select 1
After 1.59740447998e-05 sec:
3 is writable
wrote data
select 2
After 2.86102294922e-06 sec:
3 is writable
select 3 (no write)
After 2.15910816193 sec:
3 is readable
Terminal 2:
$ cat fifo2
test
# (wait a sec, then Ctrl+C)
Pipe/FIFO read attempt after writer closed
The data still in the pipe is read first before an EOF is signaled.
Windows named pipe: detect in Python on writer side when reader has closed its end without having to write data
As @eryksun pointed out above, it is actually possible to write a probing zero-length byte string using the Win32 API WriteFile
directly: if the pipe is closed, then this will return "no success" (false/0), if the pipe is alive, then "success" (true/!=0). Exactly what I was asking for. As I find this to be simpler than using NtQueryInformationFile
I'm now using the empty write method; here's a simplified example:
import ctypes
from ctypes import byref, c_ulong, c_char_p
import msvcrt
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
fifo = open('//./pipe/somepipe', 'wb')
data = b''
written = c_ulong(0)
if not kernel32.WriteFile(
msvcrt.get_osfhandle(fifo.fileno()),
c_char_p(data), 0,
byref(written),
None):
last_error = ctypes.get_last_error()
if last_error in (
0x000000E8, # ERROR_NO_DATA
# enable as required: 0x000000E9, # ERROR_PIPE_NOT_CONNECTED
):
# pipe broken
pass
else:
# something else is wrong...
pass
else:
# pipe still okay
pass
Helpful resources:
- Answer to: How to get a win32 handle of an open file in python?
- Answer to: How to use win32 API's with python? which then links to this straight hit on my question:
- Example Code - Named Pipes (Python 2.4 + ctypes on Windows)
- comments section ;)
Detect disconnect from named pipe in linux
This is same as in TCP/IP. You need to attempt to read data, if that fails with 0, pipe is closed.
read and recv:
These calls return the number of bytes received, or -1 if an error
occurred. The return value will be 0 when the peer has performed an
orderly shutdown.
There is also SIGPIPE
signal. It'll be sent when you try write to a broken pipe - pipe with no readers.
Read on closed named pipe blocks
I don't know much about fortran, but I do know you could reproduce the hanging behavior in C by using a read/write mode in your open (for example fopen("test", "r+")
The pipe doesn't get an EOF until the number of writable file descriptors on it drops to 0. When your read file descriptor is also writable, you never get EOF.
So my guess is that fortran opens in read/write mode by default, and you need to tell it not to do that. This question about a fortran readonly flag may help.
FIFO read() function gets stuck in c
The problem is that you closed the pipe in the first process. A pipe doesn't have any permanent storage, it can only hold data while it's open by at least one process. When you close the pipe, the data that you've written to it is discarded.
As a result, when the second process tries to read from the pipe, there's nothing available.
You need to keep the pipe FD open when you execute the second process. Get rid of close(fd);
in the reader program.
FIFO pipe only reads after write end has closed
Your problem comes from the buffer. FIFO use block buffer by default. So the c program won't read anything until the write buffer of the fifo in python was full. And there's two way to change this behaviour:
- specify the buffer mode:
there's three buffer mode:
- block buffer(default)
- line buffer
- no buffer at all
What meet your needs here is the line buffer, so use fifo = open("emg", "w", 1);
instead of fifo = open("emg", "w");
will fix.
number 1 here instead line buffer. python doc
- another method is force flush the buffer, use
fifo.flush
after the write operation.
Related Topics
How to Get The Output of at Command in Current or Another Terminal Window
How to Enable Mixed Mode Debugging in Visual Studio Code
How to Make Libusb Library Visible to Another Program
Udev Rules Are Not Working for Libusb on Ubuntu 12.04
How to Execute a Command in a Bash Script and Then Focus The Appearing Window
How to Lock The Cursor to The Inside of a Window on Linux
How to Create a File in Assembly with a Dynamically Specified File Path
Linux Kernel Hardware Break Points
Socket Programming Send() Return Value
How to Install and Run Tacotron2 on Ubuntu Wsl
Can't Install Using Yum in Rhel 7.1
How to I Detect Whether a Tty Belonging to a Gsm/3G-Modem Is a Data or Control Port