How can I tell if there is new data on a pipe? - c++

I'm working on Windows, and I'm trying to learn pipes, and how they work.
One thing I haven't found is how can I tell if there is new data on a pipe (from the child/receiver end of the pipe?
The usual method is to have a thread which reads the data, and sends it to be processed:
void GetDataThread()
{
while(notDone)
{
BOOL result = ReadFile (pipe_handle, buffer, buffer_size, &bytes_read, NULL);
if (result) DoSomethingWithTheData(buffer, bytes_read);
else Fail();
}
}
The problem is that the ReadFile() function waits for data, and then it reads it. Is there a method of telling if there is new data, without actually waiting for new data, like this:
void GetDataThread()
{
while(notDone)
{
BOOL result = IsThereNewData (pipe_handle);
if (result) {
result = ReadFile (pipe_handle, buffer, buffer_size, &bytes_read, NULL);
if (result) DoSomethingWithTheData(buffer, bytes_read);
else Fail();
}
DoSomethingInterestingInsteadOfHangingTheThreadSinceWeHaveLimitedNumberOfThreads();
}
}

Use PeekNamedPipe():
DWORD total_available_bytes;
if (FALSE == PeekNamedPipe(pipe_handle,
0,
0,
0,
&total_available_bytes,
0))
{
// Handle failure.
}
else if (total_available_bytes > 0)
{
// Read data from pipe ...
}

One more way is to use IPC synchronization primitives such as events (CreateEvent()). In case of interprocess communication with complex logic -- you should put your attention at them too.

Related

How can I check whether the input buffer is empty?

I'm trying to write a simple class for operating a Serial Port on Windows, using standart windows library .
I need to check whether the input buffer is empty.
So far I've tried to use SetCommEvent, using EV_RXCHAR option, however this method doesn't work. The function seems to wait for arrival of new char. If I tried to send char, sleep for a second and the apply this, the function would not return - it keeps waiting.
bool isEmpty()
{
DWORD dwEventMask = 0;
DWORD Status = 0;
if (CheckAsyncRead())
return false;
if (!SetCommMask(hPort, EV_RXCHAR)) //wait for char receival
std::cout << "Error in creating Overlapped event" << std::endl;
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (WaitCommEvent(hPort, &dwEventMask, &osReader))
{
//close event handle
return false;
}
Status = WaitForSingleObject(osReader.hEvent, 10);
//I wait for 10 ms in case the function doesn't return immediately
//Close event handle
if (Status == WAIT_OBJECT_0)
{
return false;
}
else
return true;
}
I hoped the WaitCommEvent or WaitForSingleObject would return in case any chars were present in buffer but the does not happen if there is a longer pause between receival of a character and calling of Wait function.
You can use the ClearCommError function to find out the size of the data stored in the buffer.
As a result of calling, cbInQue of the COMSTAT structure to be notified has the size of the data stored in the input buffer.
You can use ReadFile() with a handle opened with CreateFile() with the FILE_FLAG_OVERLAPPED flag. If the ReadFile() function has nothing to return, it will return a last error ERROR_IO_PENDING which means that your buffer is currently empty.

PseudoTerminal - Not read from stdin

I am creating a class where I can create multiple threads that are pseudo terminals, in order to talk to each one of them I have to create multiple files / Fifos to talk to each pseudo terminal slave, because taslking to the stdin makes any created pseudoterminal listen, the problem is that when using a fifo for input it does not work.
Here is the code
void * Terminal::tTerminal(void * pvParameters)
{
Terminal (*self) = reinterpret_cast<Terminal*>(pvParameters);
fd_set inFds;
//dup2(self->in, STDIN_FILENO);
for (;;)
{
FD_ZERO(&inFds);
FD_SET(self->in, &inFds);
FD_SET(self->masterFd, &inFds);
if (select(self->masterFd + 1, &inFds, &inFds, NULL, NULL) == -1)
{
printf("select");
}
if (FD_ISSET(self->in, &inFds))
{
self->numRead = read(self->in, self->buf, BUF_SIZE);
if (self->numRead <= 0)
exit(EXIT_SUCCESS);
if (write(self->masterFd, self->buf, self->numRead) != self->numRead)
printf("partial/failed write (masterFd)");
}
else
{
printf("partial/failed write (masterFd)");
fflush(stdout);
}
if (FD_ISSET(self->masterFd, &inFds))
{
self->numRead = read(self->masterFd, self->buf, BUF_SIZE);
if (self->numRead <= 0)
exit(EXIT_SUCCESS);
if (write(self->out, self->buf, self->numRead) != self->numRead)
printf("partial/failed write (STDOUT_FILENO)");
}
else
{
printf("partial/failed write (STDOUT_FILENO)");
fflush(stdout);
}
}
For further notices the Fifos are created correctly, the file descriptors are not 0, the master and slave are running, the only problem is in:
FD_ISSET(self->in, &inFds)
Which means it is not set,
Thanks
You should make sure the first argument to select() is the highest of all possible filedescriptors plus one, so:
select(std::max(self->masterFd, self->in) + 1, &inFds, &inFds, NULL, NULL)

How to check if WriteFile function is done

I want to check if the WriteFile function is done writing to UART so that i can call ReadFile on the same ComDev without causing an Exception.
It seems the WriteFile function can return before writing is done.
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
Sleep(1000); // complete write operation TBD
fComPortInUse = 0;
return (FALSE);
}
fComPortInUse = 0;
return (TRUE);
}
I used Sleep(1000) as an workaround, but how can i wait for an appropriate time?
You can create a Event, store it in your overlapped structure and wait for it to be signalled. Like this (untested):
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent != NULL)
{
osWrite.hEvent = hEvent;
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
WaitForSingleObject(hEvent, INFINITE);
fComPortInUse = 0;
return (FALSE);
}
CloseHandle(hEvent);
}
fComPortInUse = 0;
return (TRUE);
}
Note that depending on what else you are trying to do simply calling WaitForSingleObject() might not be the best idea. And neither might an INFINITE timeout.
Your problem is the incorrect use of the overlapped I/O, regardless to the UART or whatever underlying device.
The easiest (though not necessarily the most optimal) way to fix your code is to use an event to handle the I/O completion.
// ...
OVERLAPPED osWrite = {0,0,0};
osWrite.hEvent = CreateEvent(FALSE, NULL, NULL, FALSE);
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
DWORD Errorcode = GetLastError();
// ensure it's ERROR_IO_PENDING
WaitForSingleObject(osWrite.hEvent, INFINITE);
}
CloseHandle(osWrite.hEvent);
Note however that the whole I/O is synchronous. It's handles by the OS in an asynchronous way, however your code doesn't go on until it's finished. If so, why do you use the overlapped I/O anyway?
One should use it to enable simultaneous processing of several I/Os (and other tasks) within the same thread. To do this correctly - you should allocate the OVERLAPPED structure on heap and use one of the available completion mechanisms: event, APC, completion port or etc. Your program flow logic should also be changed.
Since you didn't say that you need asynchronous I/O, you should try synchronous. It's easier. I think if you just pass a null pointer for the OVERLAPPED arg you get synchronous, blocking, I/O. Please see the example code I wrote in the "Windows C" section of this document:
http://www.pololu.com/docs/0J40/
Your Sleep(1000); is of no use, it will only execute after the writefile completes its operation.You have to wait till WriteFile is over.
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{}
You must be knowing that anything inside conditionals will only execute if the result is true.
And here the result is sent to the program after completion(whether complete or with error) of WriteFile routine.
OK, I missed the overlapped I/O OVL parameter in the read/write code, so It's just as well I only replied yesterday as a comment else I would be hammered with downvotes:(
The classic way of handling overlapped I/O is to have an _OVL struct as a data member of the buffer class that is issued in the overlapped read/write call. This makes it easy to have read and write calls loaded in at the same time, (or indeed, multiple read/write calls with separate buffer instances).
For COM posrts, I usually use an APC completion routine whose address is passed in the readFileEx/writeFileEx APIs. This leaves the hEvent field of the _OVL free to use to hold the instance pointer of the buffer so it's easy to cast it back inside the completion routine, (this means that each buffer class instance contains an _OVL memebr that contains an hEvent field that points to the buffer class instance - sounds a but weird, but works fine).

Child process is blocked by full pipe, cannot read in parent process

I have roughly created the following code to call a child process:
// pipe meanings
const int READ = 0;
const int WRITE = 1;
int fd[2];
// Create pipes
if (pipe(fd))
{
throw ...
}
p_pid = fork();
if (p_pid == 0) // in the child
{
close(fd[READ]);
if (dup2(fd[WRITE], fileno(stdout)) == -1)
{
throw ...
}
close(fd[WRITE]);
// Call exec
execv(argv[0], const_cast<char*const*>(&argv[0]));
_exit(-1);
}
else if (p_pid < 0) // fork has failed
{
throw
}
else // in th parent
{
close(fd[WRITE]);
p_stdout = new std::ifstream(fd[READ]));
}
Now, if the subprocess does not write too much to stdout, I can wait for it to finish and then read the stdout from p_stdout. If it writes too much, the write blocks and the parent waits for it forever.
To fix this, I tried to wait with WNOHANG in the parent, if it is not finished, read all available output from p_stdout using readsome, sleep a bit and try again. Unfortunately, readsome never reads anything:
while (true)
{
if (waitid(P_PID, p_pid, &info, WEXITED | WNOHANG) != 0)
throw ...;
else if (info.si_pid != 0) // waiting has succeeded
break;
char tmp[1024];
size_t sizeRead;
sizeRead = p_stdout->readsome(tmp, 1024);
if (sizeRead > 0)
s_stdout.write(tmp, sizeRead);
sleep(1);
}
The question is: Why does this not work and how can I fix it?
edit: If there is only child, simply using read instead of readsome would probably work, but the process has multiple children and needs to react as soon as one of them terminates.
As sarnold suggested, you need to change the order of your calls. Read first, wait last. Even if your method worked, you might miss the last read. i.e. you exit the loop before you read the last set of bytes that was written.
The problem might be is that ifstream is non-blocking. I've never liked iostreams, even in my C++ projects, I always liked the simplicity of C's stdio functions (i.e. FILE*, fprintf, etc). One way to get around this is to read if the descriptor is readable. You can use select to determine if there is data waiting on that pipe. You're going to need select if you are going to read from multiple children anyway, so might as well learn it now.
As for a quick isreadable function, try something like this (please note I haven't tried compiling this):
bool isreadable(int fd, int timeoutSecs)
{
struct timeval tv = { timeoutSecs, 0 };
fd_set readSet;
FD_ZERO(&readSet);
return select(fds, &readSet, NULL, NULL, &tv) == 1;
}
Then in your parent code, do something like:
while (true) {
if (isreadable(fd[READ], 1)) {
// read fd[READ];
if (bytes <= 0)
break;
}
}
wait(pid);
I'd suggest re-writing the code so that it doesn't call waitpid(2) until after read(2) calls on the pipe return 0 to signify end-of-file. Once you get the end-of-file return from your read calls, you know the child is dead, and you can finally waitpid(2) for it.
Another option is to de-couple the reading from the reaping even further and perform the wait calls in a SIGCHLD signal handler asynchronously to the reading operations.

Why isn't this thread reading all data from the pipe consistently?

Anything wrong with this in general?
CallingFunction()
{
CreatePipe()
CreateMutex()
CreateThread( ThreadFunction )
while(there is data left to send)
{
WriteFile(send data in 256 byte chunks)
}
WaitForSingleobject() //don't return until ReadThread is done
return 0;
}
ThreadFunction()
{
WaitForSinglObject()
while(bytesRead != totalBytestoReadFileSize)
{
ReadfromPipe(in chunks)
update bytesRead++
}
ReleaseMutex()
return 0;
}
Before the calling function ends -
FileSize: 232016
BytesWrittenToPipe: 232016
BytesReadFromPipe: 231946 or 232012 or 231840 -> Why not consistent?
Expecting us to debug such an issue from pseudo code is not realistic. Use FlushFileBuffers to ensure all data in the pipe is written.