Named-pipe reading timeout - c++

I'm trying to set a timeout to the reading operation of my named pipe.
In order to read from the named pipe, I'm using the ReadFile function.
I read that a timeout can be set for this function with the SetCommTimeouts function but when I try to use it, I get system error 1: "Incorrect function".
Here is my code (this is the client side):
m_pipe = CreateFileA(pipeName, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
if (m_pipe != INVALID_HANDLE_VALUE)
{
DWORD mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
ok = SetNamedPipeHandleState(m_pipe, &mode, NULL, NULL);
COMMTIMEOUTS cto;
cto.ReadTotalTimeoutConstant = 1000;
BOOL time = SetCommTimeouts(m_pipe, &cto);
}
Am I doing something wrong or the SetCommTimeouts method is not supposed to be used with pipes? Is there any other way to get a reading timeout?

If the purpose of the timeout is to not get stuck forever you may consider a call to PeekNamedPipe(...) in a timed loop. This way you can check whether there is anything to read from time to time.
Alternatively PeekNamedPipe may be used to decide whether a read on the pipe is actually going to get anything before the read is performed. This way a "waiting" read can be avoided.

You cannot use SetCommTimeouts with named pipes. If you want timeouts, you will have to use Async I/O and implement the timeout yourself using CancelIo or CancelIoEx

ReadFile blocks until it read requested amount of bytes or error/abort happen. Overlapped works same, i.e. it completes on same conditions. Tried to implement timeouts using CancelIoEx and figured out that it loses data. Until now see no way to implement timeouts and read only part of requested amount of bytes, or read cached data.

Related

How to make asynchronous read of a file with IOCP?

I have faced an implementation problem. I am puzzled on how to implement IOCP. I have read a lot on the Internet about it, but still missing one step.
So far what I have learnt is as follows:
In order to use IOCP:
on an init function:
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // to have a max thread number available
handler = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED , 0);
CreateIoCompletionPort(handler, NULL, 0, 0); // to associate my handler with an IOCP
on a read funcion I can do sth like that:
ReadFile(..., &Overlapped); // this will return error == ERROR_IO_PENDING which is what I want - asynch read
now I have difficulties to understand next steps. Should I spawn a thread after ReadFile and wait inside that thread until GetQueuedCompletionStatus is true?
So the answer for my question is here:
https://stackoverflow.com/a/680416/2788176
In very simplistic (and a little over-simplified) terms, you tell the
IOCP about the IO jobs you want done. It will perform them
asynchronously and maintain a queue of the results of each of those
jobs. Your call to tell the IOCP about the job returns immediately (it
does not block while the IO happens). You are returned an object that
is conceptually like the .NET IAsyncResult ... it lets you block if
you choose to, or you can provide a callback, or you can periodically
poll to see if the job is complete.
IOCP implementation can be found in windows SDK.

Named pipe: ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE

I reactivated code that I am sure used to work some months ago. It drives me crazy but it does not anymore. I could not find an answer in other questions.
On the server side, I create a pipe using
#define MAX_MESSAGE_LENGTH 1024
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE);
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
auto pipe_name = _T("\\\\.\\pipe\\") + _serviceName;
HANDLE pipe = CreateNamedPipe(
pipe_name.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1,
MAX_MESSAGE_LENGTH, MAX_MESSAGE_LENGTH, // buffer lengths (advisory)
0, // default timeout of 50ms when WaitNamedPipe uses NMPWAIT_USE_DEFAULT_WAIT
&sa));
Then a thread waits for incoming clients with ConnectNamedPipe. ConnectNamedPipe blocks until a client connects with
HANDLE pipe = CreateFile(
pipe_name.c_str(), // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
FILE_ATTRIBUTE_NORMAL, // default attributes
NULL); // no template file
ConnectNamedPipe on the server then returns with TRUE and GetLastError == 0. But when it tries to call ReadFile to read incoming data on the pipe, ReadFile immediately returns FALSE and GetLastError==ERROR_BROKEN_PIPE.
On client side, CreateFile has returned GetLastError==231, "All pipe instances are busy". Although it is the only client! A call to WaitNamedPipe(pipe, 2000)returns with error code 121, "The semaphore timeout period has expired".
Increasing the number of allowed clients in CreateNamedPipe does not change anything.
It seems the pipe got completely broken in the moment the client tries to connect. But why? Both client and server run on the same machine with same user and even same session.
Another call to ConnectNamedPipe then failed with GLE=232:"The pipe is being closed".
I also had other SECURITY_ATTRIBUTES for CreateNamedPipe, which shall allow for non-elevated users to connect, but that makes no difference.
Also I tried to use CallNamedPipe on the client with the same result.
PathFileExists is the pipe killer! After hours of trying I finally found what breaks the pipe: a simple call to PathFileExists on the pipe name! This was added recently on the client side to check whether the pipe is already created. I had a look at the code changes but I totally missed that. PathFileExists correctly returns true or false but seems to mess up the pipe (as I told it did not help to allow more than one client to connect). Argh!!!

Assynchronous serial comms: why does ReadFile() set the event in the OVERLAPPED struct?

I have drawn on various sources to piece together some (multi-threaded) code to read and write from/to a serial port. It all works fine... except that the loop in the thread that does the reading from the serial port unintentionally does a busy wait. Essentially what happens repeatedly is:
An event (created outside the read loop) is reset, and its handle used as the hEvent member in an OVERLAPPED struct.
ReadFile() is passed the OVERLAPPED struct (among other parameters) and returns immediately
WaitForSingleObject() waits on the event in the OVERLAPPED struct, but always returns immediately because the event is always set after the ReadFile()
GetOverlappedResult() is then passed the same OVERLAPPED struct, returns successfully, but typically only reads 0 bytes
My expectation was that the whole point of the event was to signal when there is data available to read. But ReadFile() sets the event, and so what is the point? What am I missing?
The following stripped-back code demonstrates the issue on my system (I have COM3 connected). The full code quite happily reads and writes... but the reader suffers from the condition described above:
HANDLE portHandle = CreateFile( "COM3",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL ); // succeeds
HANDLE readerEvent = CreateEvent( 0, TRUE, FALSE, _T( "Rx Event" ) ); // succeeds
char buffer[ 200 ];
DWORD bytesRead;
OVERLAPPED reader;
memset( &reader, 0, sizeof( reader ) );
reader.hEvent = readerEvent;
ResetEvent( readerEvent );
ReadFile( portHandle, buffer, 200, &bytesRead, &reader );
if ( WaitForSingleObject( reader.hEvent, 2000 ) == WAIT_OBJECT_0 )
{
// always true, never has to wait on the event.
}
Found it: the documentation for the ReadFile function contains this paragraph:
When reading from a communications device, the behavior of ReadFile is determined by the current communication time-out as set and retrieved by using the SetCommTimeouts and GetCommTimeouts functions. Unpredictable results can occur if you fail to set the time-out values. For more information about communication time-outs, see COMMTIMEOUTS.
I was not using SetCommTimeouts() at all. Performing a GetCommTimeouts() and inspecting the results showed the port's settings were the values described in this paragraph from the COMMTIMEOUTS documentation:
A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received.
You can also use the WaitCommEvent function to wait on the event with a specific event mask. Code sample using CreateFile and WaitCommEvent: Monitoring Communications Events.

Read from serial port only when data is send from other side (c++)

I am doing serial communication in win32. I have used separate thread to write and read. This is because i have to continuously send the data till the application is running without affecting other part of the program and I have to continuously read the data from the serial port.
The main function (WINAPI WinMain) has
_beginthread(serialFunctionSend,0,(void*)12); // start new thread for send (write)
_beginthread(SerialFunctionReceive,0,(void*)10);//start new thread for receive(read)
the send function is continuously sending the data. My problem is in the receive function. It can receive the data. But I am wandering how to check whether data has been received or not . In other words, how to check our system has received any data. I have to perform some task only when something is received not when we donot receive anything at the port. So i have to exclude the condition when program has not received anything.
My "SerialFunctionReceive" code is
void SerialFunctionReceive(void * arg)
{
char inBuffer[BUF_SIZE];
while (statusRead ==true)
{
DWORD nBytesRead = serialObj.ReadTest(inBuffer, sizeof(inBuffer));
}
}
Can we do this by checking the value of inBuffer as read data is stored in it. How can we check that inBuffer has some value or not. Or is there is other options to check whether read event has taken place .
you can poll the buffer.
DWORD nBytesRead = serialObj.ReadTest(inBuffer, sizeof(inBuffer));
if (nBytesRead == 0)
{
//no data
}
else
{
//do something
}
I guess you need to do this in a while loop since you never know when you get new data.
First of all, you have to make sure your serial port is opened as an Overlapped I/O in order to send and to receive at the same time.
If you did so, the WaitForSingleObject() is useful for you.
OVERLAPPED ov = {0};
ov.hEvent = CreateEvent(NULL, true, false, NULL);
DWORD dwEvtMask;
WaitCommEvent(hSerialPort, &dwEvtMask, &ov);
WaitForSingleObject(ov.hEvent, INFINITE);
Where hSerialPort is the return value of CreateFile() who opened your serial port. The program will be blocked at the last line before any data comes in. So you don't have to poll it all the time.
See CreateFile for more detail.
And you may be interested in this page.

Deadlock with WriteFile/ReadFile

I'm using pipes and I got a kind of deadlock on WriteFile/ReadFile. Here is my code :
hProbePipeRet = CreateNamedPipe(
"\\\\.\\pipe\\probePipeRet", // pipe name
PIPE_ACCESS_DUPLEX, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
5, // client time-out
NULL); // default security attribute
First I create my pipe, then I use it like this in another application:
WriteFile(
hProbePipeRet, // handle to pipe
msg.c_str(), // buffer to write from
msg.size(), // number of bytes to write
&dwBytesWritten, // number of bytes written
NULL); // not overlapped I/O
And I receive it back with :
fSuccess = ReadFile(
myInst->hProbePipeRet, // handle to pipe
buf, // buffer to receive data
BUFSIZE, // size of buffer
&dwBytesRead, // number of bytes read
NULL); // not overlapped I/O
This is very basic and I have two more pipes that do EXACLY the same thing, the only difference is that they are in a different thread, but I need this one only for basic transactions of message.
On the first try, the informations on the pipes are read successfully, but on the second try, if I don't send at least BUFSIZE of data, both WriteFile and ReadFile will block. As I said, I have two more pipes that do the same thing, with the same functions and I don't need to send BUFSIZE of data to have a successful communication.
EDIT : Additionnal infos
The execution goes as follow : A message is sent to the server by pipe1, the message is received then it returns data with hProbePipeRet in my problematic code. The data is read by the client, printed to the screen.
Another message is dispatched using pipe1, received and the result goes again in hProbePipeRet, the client is waiting for at least BUFSIZE of information and I don't know what the server is doing but it's blocked at WriteFile.
This scenario is the same as my others pipes but I don't put hProbePipeRet in a seperate thread to read from it. I'm doing this because I need an answer right after I dispatched the message.
Perhaps you have the problem that you use blocking IO. The call to ReadFile blocks until there is something to read. If you have a loop that calls write and then read it may block in the second call.
Perhaps you should consider using async io. You call the readFile with a event. The event gets set when there is something to read. So there is no need to create multiple threads.
use PIPE_TYPE_BYTE and PIPE_READMODE_BYTE instead of the MESSAGE counter parts. Also the server must not perform any blocking read operations before any client has connected.
See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx
Edit: For the 'must not perform any blocking read operations': This can, according the the documentation lead to a race condition which actually might be your case, however it is hard to tell without seeing more of your code.