cxsp
cxsp

Reputation: 1

How to manage reads with signals in C?

I'm reading integers from a file in this way:

int v, num;
    for(;;) {
        v = read(fd, &num, sizeof(int));
        if (v == -1) {
            fprintf(stderr, "Error in read()\n");
            exit(EXIT_FAILURE);
        }
        if (v == 0) 
            break;
        [...]
    }

What does it happen if a signal arrives? How can I manage errno == EINTR? Do I have to repeat read if errno==EINTR?

Upvotes: 0

Views: 501

Answers (1)

Filipe Gonçalves
Filipe Gonçalves

Reputation: 21213

If you didn't mess with signals, you don't have to worry about it. Here's why: a signal's action is either terminate, ignore, or invoke a handler (or stop / continue, but let's ignore these), so, unless you explicitly caught any signal, then you will never have to think about EINTR - it will only happen if read(2) was interrupted by a signal handler that you set up, was invoked and returned.

If you caught a signal, then whether or not slow syscalls are automatically restarted is controlled by the SA_RESTART flag that can be set/unset in the sa_flags field of struct sigaction before setting the signal handler. If you want read(2) and others to automatically restart after the handler returns, then you must specify this flag to keep code portable (the default behavior varies across platforms).

Under some conditions, there are a couple of interfaces that are not automatically restarted even if SA_RESTART is set; refer to man 7 signal to see a list.

In case you're wondering: slow syscalls are syscalls that can block forever under certain conditions: for example, read()s from a terminal or socket, open(2) on FIFOs, wait(2) and family, file locking interfaces, some ioctl(2) calls, etc.

Upvotes: 0

Related Questions