5

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.