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?
3 Answers
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";
-
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, althoughreecho () { read -t1 LINE; echo $LINE; }; echo abcd | reecho
gives the behaviour consistent with what you descibe. Jun 15, 2016 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,– meuhJun 15, 2016 at 14:52
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).
-
-
I don't know of a way to do this using the shell, but that doesn't mean it can't be done! Jun 15, 2016 at 13:04
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.
-
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. Jun 15, 2016 at 16:24
-
1Nice, I had
pselect()
firmly in the "multiplexing" part of my brain... Jun 15, 2016 at 16:32
open()
the file (though you don't need toread()
from it). Will that be a problem?