Skip to content
Advertisement

Using a signal handler to process datas received from a fifo

I am writing a simple client/server communication with fifo but i am stuck at using a signal handler to process client request.

The server open a fifo in readonly and non blocking mode, read datas received and writes back some datas to the client fifo.

And this actually works fine when there is no signal handler on the server side. Here is the main code for both sides.

Server :

int main(int argc, char *argv[])
{
    // install handler
    struct sigaction action;

    action.sa_handler = requestHandler;

    sigemptyset(&(action.sa_mask));

    action.sa_flags = SA_RESETHAND | SA_RESTART;

    sigaction(SIGIO, &action, NULL);

    if(!makeFifo(FIFO_READ, 0644))
        exit(1);

    int rd_fifo = openFifo(FIFO_READ, O_RDONLY | O_NONBLOCK); // non blocking

    if(rd_fifo == -1)
        exit(1);

    // wait for request and answer
    while (1) {
        qWarning() << "waiting client...";
        sleep(1);
        QString msg = readFifo(rd_fifo);

        qWarning() << "msg = " << msg;

        if(msg == "ReqMode") {
            int wr_fifo = openFifo(FIFO_WRITE, O_WRONLY); // blocking
            writeFifo(wr_fifo, QString("mode"));
            break;
        } else
            qWarning() << "unknow request ..";
    }

    close(rd_fifo);
    unlink(FIFO_READ);

    return 0;
}

Client :

int main(int argc, char *argv[])
{
    int wr_fifo = openFifo(FIFO_WRITE, O_WRONLY);

    if(wr_fifo == -1)
        exit(1);

    // create a fifo to read server answer
    if(!makeFifo(FIFO_READ, 0644))
        exit(1);

    // ask the server his mode
    writeFifo(wr_fifo, QString("ReqMode"));

    // read his answer and print it
    int rd_fifo = openFifo(FIFO_READ, O_RDONLY); // blocking
    qWarning() << "server is in mode : " << readFifo(rd_fifo);

    close(rd_fifo);
    unlink(FIFO_READ);

    return 0;
}

Everything works as expected ( even if all errors are not properly handled, this is just a sample code to demonstrate that this is possible).

The problem is that the handler ( not shown here, but it only print a message on the terminal with the signal received ) is never called when the client write datas to the fifo. Beside, i have check that if i send a kill -SIGIO to the server from a bash ( or from elsewhere ) the signal handler is executed.

Thanks for your help.

Advertisement

Answer

Actually, i missed the 3 following lines on the server side :

fcntl(rd_fifo, F_SETOWN, getpid()); // set PID of the receiving process

 fcntl(rd_fifo, F_SETFL, fcntl(rd_fifo, F_GETFL) | O_ASYNC); // enable asynchronous beahviour

 fcntl(rd_fifo, F_SETSIG, SIGIO); // set the signal that is sent when the kernel tell us that there is a read/write on the fifo.

The last point was important because the default signal sent was 0 in my case, so i had to set it explicity to SIGIO to make things works. Here is the output of the server side :

waiting client... 
nb_read =  0 
msg =  "" 
unknow request .. 
waiting client... 
signal  29 
SIGPOLL 
nb_read =  7 
msg =  "ReqMode" 

Now, i guess it’s possible to handle the request inside the handler by moving what is inside the while loop into the requestHandler function.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement