6

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?

2
  • You will normally need to open() the file (though you don't need to read() from it). Will that be a problem? Commented Jun 15, 2016 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. Commented Jun 15, 2016 at 18:01

3 Answers 3

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";
2
  • 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. Commented Jun 15, 2016 at 14:46
  • 3
    In my 4.3.42 version the man page says If TIMEOUT is 0, read returns immediately, without trying to read any data,
    – meuh
    Commented Jun 15, 2016 at 14:52
7

POSIX allows non-blocking, zero-character reads which "may detect and return errors", including that the read would block:

  • open(2) the device in O_NONBLOCKing mode;
  • read(2) with a count of 0.

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).

2
  • Thanks. Can this be done from the shell? Commented Jun 15, 2016 at 12:11
  • I don't know of a way to do this using the shell, but that doesn't mean it can't be done! Commented Jun 15, 2016 at 13:04
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.

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. Commented Jun 15, 2016 at 16:24
  • 1
    Nice, I had pselect() firmly in the "multiplexing" part of my brain... Commented Jun 15, 2016 at 16:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .