I would like to be able to tell if a character special file would block if a character were read from it without actually reading a character from it. Can this be done?
Asked
Active
Viewed 1,797 times
6
-
You will normally need to `open()` the file (though you don't need to `read()` from it). Will that be a problem? – Toby Speight Jun 15 '16 at 16:45
-
Just to clarify my earlier statement - you need an open *file descriptor* to perform this test. There's no kernel interface to do this with only the *file name* of the device. – Toby Speight Jun 15 '16 at 18:01
3 Answers
7
POSIX allows non-blocking, zero-character reads which "may detect and return errors", including that the read would block:
If this read operation checks for errors in such cases, if a read would block then read will return -1 and set errno to EAGAIN (or possibly EWOULDBLOCK for sockets, but you're asking about character devices).
Stephen Kitt
- 411,918
- 54
- 1,065
- 1,164
-
-
I don't know of a way to do this using the shell, but that doesn't mean it can't be done! – Stephen Kitt Jun 15 '16 at 13:04
7
You can do this from bash using a 0 timeout to read.
if read -t 0
then read data
fi
To test a file descriptor other than stdin, say 3, use -u 3. To find how many chars are ready on stdin you can use a small perl script:
#!/usr/bin/perl
require 'sys/ioctl.ph';
$size = pack("L", 0);
ioctl(*STDIN, FIONREAD(), $size) or die "ioctl fail: $!\n";
$size = unpack("L", $size);
print "stdin ready: $size\n";
meuh
- 49,672
- 2
- 52
- 114
-
Is `read -t0` guaranteed not to read any characters from stdin, even if there is a line waiting? I don't find this behaviour documented on the bash or ksh manpages, although `reecho () { read -t1 LINE; echo $LINE; }; echo abcd | reecho` gives the behaviour consistent with what you descibe. – Charles Stewart Jun 15 '16 at 14:46
-
3In my 4.3.42 version the man page says *If TIMEOUT is 0, read returns immediately, without trying to read any data,* – meuh Jun 15 '16 at 14:52
5
From C or C++ you would normally use pselect() to test if there is data ready for reading. You can do that without having to set the file descriptor mode to non-blocking.
Toby Speight
- 8,460
- 3
- 26
- 50
peterq
- 76
- 2
-
Note that you would set the timeout to 0 seconds and 0 microseconds to do this. I wondered at first if this meant "zero timeout" or "infinite timeout", but it appears that to get the latter, you pass NULL. – Nate Eldredge Jun 15 '16 at 16:24
-
1Nice, I had `pselect()` firmly in the "multiplexing" part of my brain... – Stephen Kitt Jun 15 '16 at 16:32