I’m trying to create named pipe with O_NONBLOCK mode and listen for a read event using “SELECT” method in a separate thread. There is a problem when i’m trying to close the program after some sleeping time in the main thread. I expect that when the named pipe’s file descriptor is closed using close method, the select operation should immediately stop and return some value. But unfortunately, the select operation has no reaction when the file descriptor is closed and the thread which executes select method just hangs…
Any ideas how to solve it? The example code is below.
#include <pthread.h>
#include <limits.h>
#include <cctype>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <exception>
#define BUFFER PIPE_BUF
#define LPVOID void *
#define BOOL int
#define TRUE 1
#define CONST const
#define CHAR char
class CPipeTest
{
public:
int fd;
int nfd;
fd_set rfd;
pthread_t t;
CPipeTest() {};
~CPipeTest() {};
static LPVOID fnExecuteThread(LPVOID lpParam)
{
((CPipeTest*)lpParam)->fnRunThread();
return NULL;
}
BOOL fnRunThread()
{
printf("Going to listen...\r\n");
select(nfd, &rfd, NULL, NULL, NULL);
printf("Close listener...\r\n");
return TRUE;
}
void fnInit()
{
CONST CHAR * name = "./test_fifo1";
mkfifo(name, 0777);
fd = open(name, O_NONBLOCK | O_RDONLY);
nfd = fd + 1;
FD_ZERO(&rfd);
FD_SET(fd, &rfd);
pthread_create( &t, NULL, fnExecuteThread, (LPVOID)this);
sleep(30);
printf("Close file descriptor - listener should be closed automatically and immediately\r\n");
close(fd);
printf("Descriptor closed wait for thread to to be closed\r\n");
pthread_join(t, NULL);
printf("Thread is closed - everything is fine\r\n");
}
};
int main()
{
CPipeTest pi;
pi.fnInit();
return 0;
}
There should be two file descriptors, one for reading and another for writing.
For blocking mode, the one for writing (which you will close in the initial thread) should be opened in the initial thread, after starting the “reader” thread. The one for reading should be opened in the reader thread. For non-blocking mode, it may be done in the same thread, if you first open for reading, then for writing (or
ENXIOwill be returned for opening writer with no reader).When you close the writing side, the reading side will receive notification with
select. (If there would be a real data exchange, the followingreadwould read zero bytes, that’s how you detect EOF).If you switch to anonymous pipes, you’ll get a pair of descriptors from the
pipecall automatically.