Mercalli
Mercalli

Reputation: 709

In Windows, how to force C's fread to return even if there's no pending input?

In a Windows program with two threads: thread1 and thread2.

When thread1 is blocked in the call fread(buffer, 1, 10, stdin) waiting for input, is it possible to do something from thread2 to force fread to return?

So far I tried calling fclose(stdin) from thread2, but it doesn't seem to work. The program gets stuck at the fclose call until some input is avaible in the stdin stream.

What I'm trying to achieve is to terminate thread1 gracefully instead of just killing it with TerminateThread, because there's some work that thread1 has to do at the end.

Another thing to consider is that stdin is one end of a named pipe. I don't have control over the program at the other end of the pipe.
What I need is just to disconnect my program from its end of the pipe (stdin in this case).

Upvotes: 2

Views: 428

Answers (2)

HrW
HrW

Reputation: 256

If you can't use CancelSynchronousIo you can close the underlying file handle with CloseHandle, like this:

CloseHandle((HANDLE)_get_osfhandle(_fileno(stdin))) ;

That should cause fread to return.

Upvotes: 2

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215193

Calling fclose(stdin) is a very bad idea; it causes undefined behavior if it happens before the fread (which it's not ordered with respect to) or if the thread calling fread does anything else with stdin after fread returns, and it does not unblock the fread since fclose cannot proceed until it obtains a lock on stdin, which the in-progress fread is excluding.

stdio is just fundamentally unsuitable for what you want to do here. You could patch it up via forwarding through a second pipe, with yet another thread reading from stdin and writing into your new pipe. Then you could abort an fread on the read end of your pipe by closing the write end of it. The extra thread would still be stuck, but that doesn't really matter if you're going to be terminating anyway. Alternatively (and this is probably cleaner) you would use file descriptors (or Windows file handles) instead of stdio and poll (or the Windows equivalent) to determine whether there's input to be read. You could combine these approaches to put the Windows-specific file handle logic in the extra thread (thus being able to terminate it cleanly) and continue to use portable stdio in your program logic thread.

Upvotes: 5

Related Questions