15

I have a popen() function which executes tail -f sometextfile. Aslong as there is data in the filestream obviously I can get the data through fgets(). Now, if no new data comes from tail, fgets() hangs. I tried ferror() and feof() to no avail. How can I make sure fgets() doesn't try to read data when nothing new is in the file stream?

One of the suggestion was select(). Since this is for Windows Platform select doesn't seem to work as anonymous pipes do not seem to work for it (see this post).

dragosht
  • 3,237
  • 2
  • 23
  • 32
SinisterDex
  • 811
  • 2
  • 10
  • 13

5 Answers5

31

In Linux (or any Unix-y OS), you can mark the underlying file descriptor used by popen() to be non-blocking.

#include <fcntl.h>

FILE *proc = popen("tail -f /tmp/test.txt", "r");
int fd = fileno(proc);

int flags;
flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);

If there is no input available, fgets will return NULL with errno set to EWOULDBLOCK.

ACK_stoverflow
  • 3,148
  • 4
  • 24
  • 32
DGentry
  • 16,111
  • 8
  • 50
  • 66
15

fgets() is a blocking read, it is supposed to wait until data is available if there is no data.

You'll want to perform asynchronous I/O using select(), poll(), or epoll(). And then perform a read from the file descriptor when there is data available.

These functions use the file descriptor of the FILE* handle, retrieved by: int fd = fileno(f);

Sufian
  • 8,627
  • 4
  • 22
  • 24
  • 1
    Definitely use select() - if you have a FILE * and you need a file descriptor, use fileno(). If you have a file descriptor and you need a FILE *, use fdopen(). – plinth Sep 29 '08 at 18:00
  • Unfortunately, I think select() doesn't work on pipes under Windows. – Roddy Sep 30 '08 at 16:17
  • 2
    Mixing select() and fgets() is dangerous. A FILE* contains internal buffers that select() isn't aware of. The correct answer is O_NONBLOCK. – Alcaro Jun 25 '19 at 12:55
0

I you would use POSIX functions for IO instead of those of C library, you could use select or poll.

Paul
  • 13,042
  • 3
  • 41
  • 59
Kasprzol
  • 4,087
  • 22
  • 20
0

You can instead try reading sometextfile using low-level IO functions (open(), read(), etc.), like tail itself does. When there's nothing more to read, read() returns zero, but will still try to read more the next time, unlike FILE* functions.

Lev
  • 6,487
  • 6
  • 28
  • 29
0

i solved my problems by using threads , specifically _beginthread , _beginthreadex.

SinisterDex
  • 811
  • 2
  • 10
  • 13