check whether fgets would block - c++

I was just wondering whether in C is it possible to peek in the input buffer or perform similar trickery to know whether a call to fgets would block at a later time.
Java allows to do something like that by calling BufferedReader.ready(), this way I can implement console input something like this:
while (on && in.ready()) {
line = in.readLine();
/* do something with line */
if (!in.ready())
Thread.sleep(100);
}
this allows an external thread to gracefully shutdown the input loop by setting on to false; I'd like to perform a similar implementation in C without resorting to non portable tricks, I already know I can make a "timed out fgets" under unix by resorting to signals or (better, even though requering to take care of buffering) reimplement it on top of recv/select, but I'd prefer something that would work on windows too.
TIA

Suggest to go with socket I/O routines,preferably poll() with required millisecond as timeout and eventually you can interpret timeout ( return value = -1 ) as unavailability of data in input buffer.
In my opinion,there is no non-blocking standard I/O function to achieve this functionality.

I'm not certain what are you talking about: a socket or a file handle?
For files there should be no blocking. The function returns immediately (besides of the I/O invocation itself).
For sockets - you may use the ioctlsocket function:
The following tells if there's a rcv data pending:
ULONG nSize;
ioctlsocket(sock, FIONREAD, &nSize);
The following transfers the socket into non-blocking mode:
ULONG nEnable = 1;
ioctlsocket(sock, FIONBIO, &nEnable);
When in Non-blocking mode - functions on socket never block. If they can't fulfill the request they return an error, and the error code is WSAEWOULDBLOCK
Plus, on Windows there're dozens of much more efficient methods. Those are:
Using Overlapped I/O. This is non-trivial, but gives superior performance
Associating socket with a waitable event. This transfers the socket to a non-blocking mode, plus the specified event is signaled when a network event occurs.
Associate it with the window handle. This is convenient for UI-oriented programs.

Related

Best way to exit application at CTRL+C interrupt on Linux. (C/C++)

My application checks for user input in its main thread:
while (running)
{
std::string console;
if (std::getline(std::cin, console))
{
process(&console);
}
}
Before that I have setup a sigaction to detect CTRL+C in conjunction with a function handler to shutdown other threads.
Now, when a SIGINT occurs the application crashes; GDB output:
I was looking around and found other solutions such as non-blocking input reading: (pseudo-code)
while (running)
{
if (input_avail())
{
getinput
process
}
else
sleep(1);
}
But even that fails for me at the sleep function (nanosleep):
So I'm quite curious on how other people achieve this?
(Using g++ v4.8.2 Kernel 3.10)
Additional info requested:
Before the main thread loop:
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = signalinfo;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGTERM, &sigIntHandler, NULL);
sigaction(SIGQUIT, &sigIntHandler, NULL);
sigaction(SIGINT, &sigIntHandler, NULL);
Signal handler:
void signalinfo(int signum)
{
// Only setting a flag so threads know to exit.
pCore->Termination(signum);
}
Not sure if it answers your question, but the documentation of the XBoard protocol explains some common strategies how engine engine handle reading from stdin.
It basically sketches how you might implement your non-blocking pseudo code.
Source: XBoard protocol (6. Hints on input/output)
... on the input side, you are likely to want to poll during your search and stop it if new input has come in. If you implement pondering, you'll need this so that pondering stops when the user makes a move. You should also poll during normal thinking on your move, so that you can implement the "?" (move now) command, and so that you can respond promptly to a "result", "force", or "quit" command if xboard wants to end the game or terminate your engine. Buffered input makes polling more complicated -- when you poll, you must stop your search if there are either characters in the buffer or characters available from the underlying file descriptor.
The most direct way to fix this problem is to use unbuffered operating system calls to read (and poll) the underlying file descriptor directly. On Unix, use read(0, ...) to read from standard input, and use select() to poll it. See the man pages read(2) and select(2). (Don't follow the example of GNU Chess 4 and use the FIONREAD ioctl to poll for input. It is not very portable; that is, it does not exist on all versions of Unix, and is broken on some that do have it.) On Win32, you can use either the Unix-like _read(0, ...) or the native Win32 ReadFile() to read. Unfortunately, under Win32, the function to use for polling is different depending on whether the input device is a pipe, a console, or something else. (More Microsoft brain damage here -- did they never hear of device independence?) For pipes, you can use PeekNamedPipe to poll (even when the pipe is unnamed). For consoles, you can use GetNumberOfConsoleInputEvents. For sockets only, you can use select(). It might be possible to use WaitForSingleObject more generally, but I have not tried it. Some code to do these things can be found in Crafty's utility.c, but I don't guarantee that it's all correct or optimal.
A second way to fix the problem might be to ask your I/O library not to buffer on input. It should then be safe to poll the underlying file descriptor as described above. With C, you can try calling setbuf(stdin, NULL). However, I have never tried this. Also, there could be problems if you use scanf(), at least with certain patterns, because scanf() sometimes needs to read one extra character and "push it back" into the buffer; hence, there is a one-character pushback buffer even if you asked for stdio to be unbuffered. With C++, you can try cin.rdbuf()->setbuf(NULL, 0), but again, I have never tried this.
A third way to fix the problem is to check whether there are characters in the buffer whenever you poll. C I/O libraries generally do not provide any portable way to do this. Under C++, you can use cin.rdbuf()->in_avail(). This method has been reported to work with EXchess. Remember that if there are no characters in the buffer, you still have to poll the underlying file descriptor too, using the method described above.
A fourth way to fix the problem is to use a separate thread to read from stdin. This way works well if you are familiar with thread programming. This thread can be blocked waiting for input to come in at all times, while the main thread of your engine does its thinking. When input arrives, you have the thread put the input into a buffer and set a flag in a global variable. Your search routine then periodically tests the global variable to see if there is input to process, and stops if there is. WinBoard and my Win32 ports of ICC timestamp and FICS timeseal use threads to handle multiple input sources.

What is an overlapped I/O alternative to WaitNamedPipe?

The WaitNamedPipe function allows a pipe client application to synchronously wait for an available connection on a named pipe server. You then call CreateFile to open the pipe as a client. Pseudocode:
// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
if (WaitNamedPipe says connection is ready) {
hPipe = CreateFile(...);
if (hPipe ok or last error is NOT pipe busy) {
break; // hPipe is valid or last error is set
}
} else {
break; // WaitNamedPipe failed
}
}
The problem is that these are all blocking, synchronous calls. What is a good way to do this asynchronously? I can't seem to find an API that uses overlapped I/O to do this, for example. For example, for pipe servers the ConnectNamedPipe function provides an lpOverlapped parameters allowing for a server to asynchronously wait for a client. The pipe server can then call WaitForMultipleObjects and wait for the I/O operation to complete, or any other event to be signaled (for example, an event signaling the thread to cancel pending I/O and terminate).
The only way I can think of is to call WaitNamedPipe in a loop with a short, finite timeout and check other signals if it times out. Alternatively, in a loop call CreateFile, check other signals, and then call Sleep with a short delay (or WaitNamedPipe). For example:
HANDLE hPipe;
while (true) {
hPipe = CreateFile(...);
if (hPipe not valid and pipe is busy) {
// sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
Sleep(100);
// TODO: check other signals here to see if we should abort I/O
} else
break;
}
But this method stinks to high heaven in my opinion. If a pipe isn't available for awhile, the thread continues to run - sucking up CPU, using power, requiring memory pages to remain in RAM, etc. In my mind, a thread that relies on Sleep or short timeouts does not perform well and is a sign of sloppy multi-threaded programming.
But what's the alternative in this case?
WaitNamedPipe is completely useless, and will just use all the cpu if you specify a timeout and there's no server waiting for it.
Just call CreateFile over and over with a Sleep like you're doing, and move it to other threads as you see appropriate. There is no API alternative.
The only "benefit" WaitNamedPipe provides is if you want to know if you can connect to a named pipe but you explicitly don't want to actually open a connection. It's junk.
If you really want to be thorough, your only options are
Ensure that whatever program is opening the named pipe is always calling CreateNamedPipe again immediately after it's named pipe is connected to.
Have your program actually check if that program is running.
If your intent is really not to have additional connections, still call CreateNamedPipe, and when someone connects, tell them to go away until they're waited a given amount of time, the close the pipe.
Why can't the server just create more pipes? The performance hit in the scenario you describe isn't a problem if it is rare.
I.e. if there are usually enough pipes to go round what does it matter if you use CreateFile/Sleep instead of WaitForMultipleObjects? The performance hit will not matter.
I also have to question the need for overlapped IO in a client. How many servers is it communicating with at a time? If the answer is less than, say, 10 you could reasonably create a thread per connection.
Basically I am saying I think the reason there is no overlapped WaitforNamedPipe is because there is no reasonable use-case which requires it.
You can open the pipe file system at \\.\pipe\ and then use DeviceIoControl to send FSCTL_PIPE_WAIT.

effect of SELECT on read() in linux

I have a legacy code which is doing this:
select(nFD + 1, &tReadFds, NULL, NULL, &timer);
.............
if (FD_ISSET(nFD, &tReadFds))
n = read(nFD,len,x);
is the read gonna read the whole receive buffer(nFD), assuming 'len' and 'x' are big enough.
I think SELECT here is acting as just a way of blocking till data becomes available in recv buffer.
In a nutshell, select is a function that you can call without blocking (i.e. it returns immediately), and upon return it will tell you a list of file descriptors on which you can call read (or write) without blocking.
Such a function is crucial if you want to provide a persistent service while processing I/O with only a single thread: You cannot afford to do nothing while you are waiting for I/O, and so you need a deterministic method to ensure that you can do non-blocking I/O.
Edit. Here's an example of a typical single-threaded select-server, in pseudo-code:
while (true)
{
select(...);
read_available_data();
process_data_and_do_work(); // expensive
}
Such a server never has to be idle, and the expensive processing function can take up almost all the available computing time (it just has to make sure to return when it needs more data). I think select even allows for a context switch, so this will play nice in a multi-process environment.
The code snippet is calling select() with a non-NULL timeout parameter. The code is waiting up to some maximum amount of time for the socket to become readable. If the timeout elapses, the socket is not readable and FD_ISSET() will return false, skipping the read() call. However, if the socket becomes readable before the timeout elapses, FD_ISSET() will return true, and a call to read() is quaranteed not to block the calling thread. It will return immediately, either returning whatever data is currently in the socket's receive buffer (up to len bytes max), or returning 0 if the remote party has disconnected gracefully.

Read/write into a device in C++

How can I read/write to a device in C++? the device is in /dev/ttyPA1.
I thought about fstream but I can't know if the device has output I can read without blocking the application.
My goal is to create and application where you write something into the terminal and it gets sent into /dev/ttyPA1. If the device has something to write back it will read it from the device and write to screen. If not it will give the user prompt to write to the device again.
How can I do this?
Use open(2), read(2), and write(2) to read from and write to the device (and don't forget to close(2) when you're done). You can also use the C stdio functions (fopen(3) and friends) or the C++ fstream classes, but if you do so, you almost definitely want to disable buffering (setvbuf(3) for stdio, or outFile.rdbuf()->pubsetbuf(0, 0) for fstreams).
These will all operate in blocking mode, however. You can use select(2) to test if it's possible to read from or write to a file descriptor without blocking (if it's not possible, you shouldn't do so). Alternatively, you can open the file with the O_NONBLOCK flag (or use fcntl(2) to set the flag after opening) on the file descriptor to make it non-blocking; then, any call to read(2) or write(2) that would block instead fails immediately with the error EWOULDBLOCK.
For example:
// Open the device in non-blocking mode
int fd = open("/dev/ttyPA1", O_RDWR | O_NONBLOCK);
if(fd < 0)
; // handle error
// Try to write some data
ssize_t written = write(fd, "data", 4);
if(written >= 0)
; // handle successful write (which might be a partial write!)
else if(errno == EWOULDBLOCK)
; // handle case where the write would block
else
; // handle real error
// Reading data is similar
You can use fstream, but you're going to have to look up the specifications for how your device would like to receive data. Some devices will be just fine using ASCII data, other devices will need a specific binary sequence of data bits/bytes. You may also have to write custom serialization objects that overload the operator<< and operator>> functions for the data you're trying to write. Either that, or you could use the read() and write() methods to read/write raw binary data from/to buffer arrays you've allocated in your program.
Edit: if you're concerned about blocking behavior, then you have two choices. You will either have to use the POSIX API, and check your opened file-descriptor with either poll() or select() to see if data is available, or you will have to keep any file-writing or reading calls in a set of separate threads that can basically act as asynchronous read/write actions. So you would basically send a message to the reader/writer thread, and that thread would block if needed on the fstream calls, yet the rest of your program could continue to function. Your program though may not be designed for threads, and if that's the case, then the POSIX API would be the only way to-go.

Callbacks and Delays in a select/poll loop

One can use poll/select when writing a server that can service multiple clients all in the same thread. select and poll, however need a file descriptor to work. For this reason, I am uncertain how to perform simple asynchronous operations, like implementing a simple callback to break up a long running operation or a delayed callback without exiting the select/poll loop. How does one go about doing this? Ideally, I would like to do this without resorting to spawning new threads.
In a nutshell, I am looking for a mechanism with which I can perform ALL asynchronous operations. The windows WaitForMultipleObjects or Symbian TRequestStatus seems a much more suited to generalized asynchronous operations.
For arbitrary callbacks, maintain a POSIX pipe (see pipe(2)). When you want to do a deferred call, write a struct consisting of a function pointer and optional context pointer to the write end. The read end is just another input for select. If it selects readable, read the same struct, and call the function with the context as argument.
For timed callbacks, maintain a list in order of due time. Entries in the list are structs of e.g. { due time (as interval since previous callback); function pointer; optional context pointer }. If this list is empty, block forever in select(). Otherwise, timeout when the first event is due. Before each call to select, recalculate the first event's due time.
Hide the details behind a reasonable interface.
select() and poll() are syscalls - it means that your program is calling OS kernel to do something and your program can do nothing while waiting for return from kernel, unless you use other thread.
Although select() and poll() are used for async I/O, these functions (syscalls) are not async - they will block (unless you specify some timeout) until there is something happened with the descriptor you are watching.
Best strategy would be to check descriptors time to time (specifying small timeout value), and if there is nothing, do what you want to do in idle time, otherwise process I/O.
You could take advantage of the timeout of select() or poll() to do your background stuff periodically:
for ( ;; ) {
...
int fds = select(<fds and timeout>);
if (fds < 0) {
<error occured>
} else if if (fds == 0) {
<handle timeout, do some background work.>
} else {
<handle the active file descriptors>
}
}
For an immediate callback using the select loop, one can use one of the special files like /dev/zero that are always active. The will allow select the exit soon but will allow other files to become active as well.
For timed delays, I can only thing of using the timeout on select.
Both of the above don't feel great, so please send better answers.