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?

  • 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

You can do this from bash using a 0 timeout to read.

if read -t 0
then read data

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:

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, 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
  • 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 '16 at 14:52

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

  • Thanks. Can this be done from the shell? – Charles Stewart Jun 15 '16 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! – Stephen Kitt Jun 15 '16 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. – Nate Eldredge Jun 15 '16 at 16:24
  • 1
    Nice, I had pselect() firmly in the "multiplexing" part of my brain... – Stephen Kitt Jun 15 '16 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.