Deadlock with WriteFile/ReadFile - c++

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.

Related

How to use win32 pipe on single application

I'm trying to write to a pipe I created locally (in the same application)
At the moment I have this:
audioPipe = CreateNamedPipe(
L"\\\\.\\pipe\\audioPipe", // name of the pipe
PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
PIPE_TYPE_MESSAGE, // send data as a byte stream
1, // only allow 1 instance of this pipe
0, // no outbound buffer
0, // no inbound buffer
0, // use default wait time
NULL // use default security attributes
);
I don't know how to actually write data to it. I guess using WriteFile() but is there more to it? All examples I read seem to be using a client-server system and I don't need that. I just need to write data to the pipe (so ffmpeg picks it up, hopefully)
Based on comments, you are creating a named pipe that the command-line FFMPEG app will connect to. In order for that to work, you need to do three things:
change your call to CreateNamedPipe() to use PIPE_TYPE_BYTE instead of PIPE_TYPE_MESSAGE, as you will be streaming raw data live to FFMPEG, not messages. That will allow FFMPEG to read data from the pipe using whatever arbitrary buffers, etc it wants, as if it were reading from a real file directly.
audioPipe = CreateNamedPipe(
L"\\\\.\\pipe\\audioPipe", // name of the pipe
PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
PIPE_TYPE_BYTE, // send data as a byte stream
1, // only allow 1 instance of this pipe
0, // no outbound buffer
0, // no inbound buffer
0, // use default wait time
NULL // use default security attributes
);
you need to call ConnectNamedPipe() to accept a connection from FFMPEG before you can then write data to it.
ConnectNamedPipe(audioPipe, NULL);
when running FFMPEG, specify your pipe name as the input filename using the -i parameter, eg: ffmpeg -i \\.\pipe\audioPipe.
There's nothing more to this than calling WriteFile. You'll also need to call ConnectNamedPipe before calling WriteFile to wait for the client to connect.
The client reads from the pipe by opening a handle with CreateFile and then reading using ReadFile.
For a stream of bytes you need PIPE_TYPE_BYTE. Are you sure you want to specify 0 for the buffer sizes?

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.

Wait for data on COM port?

I'm looking for a way to get a Windows serial port to timeout until it has received data. It would be nice if there was some kind of event that triggered or a function to do exactly what I want.
This is my current implementation.
void waitforCom(unsinged char byte)
{
while (true)
{
ClearCommError(serial_handle, &errors, &status);
if (status.cbInQue>0)
{
//check if correct byte
break;
}
}
}
Another API call you could be using is WaitCommEvent().
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363479(v=vs.85).aspx
This call can work asynchronously since it takes an OVERLAPPED object as a parameter. In your case you'd want to simply wait on the EV_RXCHAR event to let you know data has arrived:
OVERLAPPED o = {0};
o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
SetCommMask(comPortHandle, EV_RXCHAR);
if (!WaitCommEvent(comPortHandle, &commEvent, &o))
{
// Check GetLastError for ERROR_IO_PENDING, if I/O is pending then
// use WaitForSingleObject() to determine when `o` is signaled, then check
// the result. If a character arrived then perform your ReadFile.
}
Alternatively you could do the same thing by having a thread with an outstanding ReadFile call, but using the OVERLAPPED object instead of blocking as MSalters recommends.
I'm not really a specialist when it comes to WinApi, but there's a whole article on the Microsoft Developer Network, that covers the subject of serial communications. The article mentions the subject of waiting for the data from a port, and it's supplied with an example.
At the winAPI level, for most applications you need to dedicate a thread to serial port input because ReadFile is a blocking call (but with a timeout). The most useful event you can get is having ReadFile return. Just put ReadFile in a loop in a thread and generate your own event or message to some other thread when ReadFile gets some data.

Named-pipe reading timeout

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.