use poll() timeout only for new data on socket
Probably been answered in the linked posts, but the basic idea is that the poll
, select
, and other mechanisms do not tell you when there is new data on the socket. As you mention correctly, they only tell you when a read()
would not block.
You may use EPOLLET
with Linux's epoll(7)
interface (other systems might have other equivalents) to do what you want; however keep in mind this is not portable.
The correct and accepted design is to either consume the network buffer fully, keep partial messages in a application-defined buffer (i.e. not in the socket's buffer) and keep track of how much additional data you need to read from the network.
poll() returns both, POLLPRI & POLLERR
I've found some answer alluding to your question at: http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/t/182883
I just ran into the POLLERR thing you're seeing too. Turns out this is
how all sysfs files work, and you're using gpio through the sysfs
interface.From the sysfs GPIO kernel document: If the pin can be configured as
interrupt-generating interrupt and if it has been configured to
generate interrupts (see the description of "edge"), you can poll(2)
on that file and poll(2) will return whenever the interrupt was
triggered. If you use poll(2), set the events POLLPRI and POLLERR.
Also, if you look take a look at the kernel code in fs/sysfs/file.c,
you'll see that sysfs_poll returns DEFAULT_POLLMASK | POLLERR |
POLLPRI.All that said, it does seem strange that sysfs files return
POLLERR, I'm not sure why they chose to do that.
Poll() on Named Pipe returns with POLLHUP constantly and immediately
Because pipes provide only a single unidirectional channel (not a separate bidirectional channel for each client like a socket), they are normally used when you have just one process that needs to send data to only one other process. When the writer closes the pipe, POLLHUP
(hangup) tells the reader that the pipe is closed and it can finish processing and terminate.
It is possible to use a pipe with multiple writers but you will need to be careful if the messages could be larger than PIPE_BUF
or 512 bytes. Otherwise, because it is only a single channel, the messages from multiple writers writing at the same time could be interleaved. Also because it is a single channel you won't be able to tell whether a long message is a single write from one client or multiple writes from multiple clients, unless you have some convention like one line (terminated by a newline) per client message.
POLLHUP
indicates that the last writer has closed the pipe, and persists until another process opens the pipe for writing or it is closed by all readers. If you don't want this, open the pipe with O_RDWR
instead of O_RDONLY
so that the pipe will stay open. This works because then there will always be a writer (your program) as long as you have it open.
polling file descriptor
The select
call should block until the file descriptor is readable.
What may be happening is that the device driver does not support the select
call, and so it exits immediately rather than blocking.
Another possibility is that the call to gpio_open
does not actually give you a real Unix file descriptor. If that were open("/dev/gpio", O_RDWR)
or something like that I'd have a lot more faith in it.
Level triggered interrupts with GPIO on an embedded Linux device
I finally figured out the answer. I need to read the GPIO's value file before emptying the FIFO to ensure things are in a good state the next time poll() is called. Here's the change to the pseudo code:
GetByte() {
Is there data in the FIFO? {
Read the GPIO value file
Read a byte.
Return
}
Call poll() to wait for the data {
Is there data in the FIFO? {
Read a byte.
Return
}
}
}
I always try to read a byte if one is available. If it's the last byte in the FIFO, I read the GPIO value file first. I know the level triggered interrupt line is high when I do this, so I can safely clear any pending file events that poll() might see. Now I read the byte.
Now when I call poll(), I know it won't return unless it sees the rising edge from the interrupt. Simple fix, but it wasn't until I read a comment in kernel/fs/sysfs/file.c until I fully understood what I needed to do.
Related Topics
Path Environment Variable in Linux
Add a Directory When Creating Tar Archive
When Is The System Call Set_Tid_Address Used
Finding Processor Id in Which Process Is Running [Through Command/Interface Similar to Top]
How to Generate Files in a Docker Container for Having The Same Owner as The Host's User
Tail a Log into an Excerpt in Real Time
How to Run 16 Bit Code on 32 Bit Linux
Raspberry Pi: Spi Not Working, Spi_Bcm2835 Not Showing with Lsmod
How to Get Icecast to Run on Port 80
How to Make 'Docker Run' Inherit Ulimits
Capturing User-Space Assembly with Ftrace and Kprobes (By Using Virtual Address Translation)
Setting Path to Shared Library Inside a Makefile for Compile
Lapack/Blas/Openblas Proper Installation from Source - Replace System Libraries with New Ones
Awk Command to Create Sha2 of Individual Column and Paste into New File
Libcurl with Libssh2 - One or More Libs Available at Link-Time Are Not Available Run-Time
Elk Not Passing Metadata from Filebeat into Logstash
How to Solve Ssh: /Usr/Lib64/Libcrypto.So.10: No Version Information Available