1

From this post it sounds like fgets() is meant to be a blocking call, however, this man page shows that if set as non-blocking, it will return NULL and errno would be EWOULDBLOCK if no data is ready to be read, so my assumption is that it is indeed possible to use it as non-blocking.

I'm aware of select()and friends, I'd just like to know if it's safe to use it as non-blocking? and if it's not, what are those reasons?‎

Community
  • 1
  • 1
user1024718
  • 573
  • 6
  • 18

1 Answers1

0

I'd just like to know if it's safe to use it as non-blocking? and if it's not, what are those reasons?‎

It depends on what you mean by "safe". C itself has no concept of non-blocking I/O, so if you're writing code that must be widely portable then even supposing that non-blocking I/O is an available alternative is unsafe.

If you're writing for a more specific environment, for example a POSIX environment, then you may be able to rely on the availability of non-blocking I/O, but you should consider the specifications of that environment to determine what behavior you may be able to expect from fgets() when the file you specify to it is, in some relevant sense, in non-blocking mode. POSIX does specify that fgets() shall fail with an error under the same conditions that fgetc() does, one of which is that

The O_NONBLOCK flag is set for the file descriptor underlying stream and the thread would be delayed in the [fgets()] operation.

With that being the case, if you're defining "safe" as "specified by POSIX" then yes, relying on fgets() not to block when the underlying underlying open file description is in non-blocking mode is safe.

@R.. asserts in comments that that using stdio functions on a file that is in non-blocking mode may produce data loss. That's plausible, but I have not yet found the basis for that assertion. I'm not prepared to contradict him on that point, however, so again, whether what you propose is "safe" depends on just what you mean by that term.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • POSIX does specify. `EAGAIN` is a mandatory error for `fgetc` (in terms of which `fgets` is defined), and on error, the `ferror` indicator is set and the state of the buffers and file position is not specified. Thus you **will get data loss** trying to use stdio in non-blocking mode. – R.. GitHub STOP HELPING ICE Feb 28 '17 at 22:55
  • @R.., right you are. That is, `fgets()`'s docs refer to `fgetc()` for error conditions, which I overlooked. It's *general* behavior is not defined in terms of `fgetc()`. I will update my answer momentarily. – John Bollinger Feb 28 '17 at 23:00
  • @R.. sorry, what do you mean with you will get data loss? Does that mean that's in some implementations it will work while some you won't get the data you expect upon the next available read? – user1024718 Feb 28 '17 at 23:04
  • @JohnBollinger thanks for the answer, it makes sense now. – user1024718 Feb 28 '17 at 23:09
  • @R..: A call to `clearerr()` should clear the error, but you are right in that you don't know what happened to buffered data at the point the error was detected by the function. Perhaps change the stream to be unbuffered as well? – jxh Feb 28 '17 at 23:17
  • @JohnBollinger I probably misused the term "safe", my expectation would be that even when in non-blocking mode, fgets will eventually get the data from the pipe (when becomes available). Though, from R's comment, now I'm concerned that you may get partial data from it. – user1024718 Feb 28 '17 at 23:24
  • I'm not clear if there are likely ways data loss would happen with a pipe (as opposed to a seekable stream), but it seems C and POSIX are pretty loose on making guarantees about what happens when a read error is encountered. – R.. GitHub STOP HELPING ICE Mar 01 '17 at 00:02