BrianChen
BrianChen

Reputation: 183

Why I can't receive SIGPOLL signal from ioctl function?

I got a strange problem that I can't solve. This is my code.

#include <stdio.h>
#include <stropts.h>
#include <signal.h>
#include <sys/types.h>

void handle_signal(int s)
{
    char c = getchar();
    printf("got char '%c'\n");
    if(c == 'q')
    {
        exit(0);
    }
}

int main(int argc, char** argv)
{
    sigset(SIGPOLL, handle_signal);
    ioctl(0, I_SETSIG, S_RDNORM);
    printf("type q to exit");
    while(1);
    return 0;
}

When I run this program, I type character in terminal but it did not work!!! I can not receive SIGPOLL signal. Have someone can give me some advice? By the way, my operating system is ubuntu 12.04.

Upvotes: 2

Views: 671

Answers (1)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136208

On Linux it needs to set O_ASYNC flag and F_SETOWN property on the file descriptor to get SIGIO signal (a synonym of SIGPOLL). And the signal handler can only call async-signal safe functions:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ctype.h>

void handle_signal(int) { // Can only use async-signal safe functions here.
    char msg[] = "got char c\n";
    char* c = msg + (sizeof msg - 3);
    if(1 != read(STDIN_FILENO, c, 1) || !isprint(*c))
        return;
    write(STDOUT_FILENO, msg, sizeof msg - 1);
    if(*c == 'q')
        exit(EXIT_SUCCESS);
}

int main() {
    printf("type q to exit\n");

    signal(SIGIO, handle_signal);
    fcntl(STDIN_FILENO, F_SETFL, O_ASYNC | fcntl(STDIN_FILENO, F_GETFL));
    fcntl(STDIN_FILENO, F_SETOWN, getpid());

    sigset_t mask;
    sigemptyset(&mask);
    for(;;)
        sigsuspend(&mask);

    return EXIT_SUCCESS;
}

You may also like to have a look at F_SETSIG that allows receiving a signal of your choosing and extra information into the signal handler.

Upvotes: 3

Related Questions