how to prevent fgets blocks when file stream has n

2019-01-09 15:28发布

问题:

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

回答1:

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.



回答2:

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



回答3:

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.



回答4:

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



回答5:

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



标签: c popen fgets