Impact of Signals on Unix/Linux System Calls

poornaMoksha's Avatar author of Impact of Signals on Unix/Linux System Calls
This is an article on Impact of Signals on Unix/Linux System Calls in C.
Suppose a system call was blocked due to some reason (like waiting for a read of some data on terminal) and during this time a signal occurs. Do you know what happens in this scenario?

In this article we will discuss the impact of signals on system calls.

System calls are different from normal function calls as a system call takes the flow control all the way to kernel. System calls are divided into two categories :
  • Slow system calls
  • Rest of the system calls
Now, what are Slow system calls ?

Slow system calls are those that can block for ever. These calls usually wait for a condition to occur and these calls can wait for infinite time if the condition does not occur. For example :
  1. The 'pause()' function call, which by default puts the calling process into sleep until and unless a signal is caught by this process.
  2. The 'read()' function calls to pipes(for example) which can block for ever until some data is present.
  3. The 'write()' function calls to pipes(for example) which can block for ever until the pipe is ready to accept the data.
  4. Some 'ioctl()' functions.
The alternative definitions of the slow system calls could be :

"The system calls that can take time to execute if/when operating on a slow device (like pipe, terminal)"

If (lets say) read() function has received and transfered some data to application and is waiting to receive the rest of the data in order to give application the complete data it requested. Suppose, at this very moment a signal occurred. Now, in todays POSIX compliant systems a read() call would not fail rather it would return partial success with the partial amount of data it could read for the application. Same goes for a system function call like 'write()' which would return partial success with writing partial data that it could.

But, what does this behavior mean? Does the application need to handle the partial success cases? Does that mean some more checks in the code like :

  if ((n = read(fd, buffer, BUFFERSIZE)) < 0) {
      if (errno == EINTR)
          goto again; /* Seems like an interrupted system call, go back and try to execute once again */
      /* handle other errors */
Thankfully, the answer to the above questions is NO. In modern day POSIX compliant systems, the interrupted system calls are restarted automatically by default. This takes away the overhead from an application programmer to test each time whether the a call to read() or write() was a complete success or a partial success.

An Interesting Example

Now, we understand the process that a system call is interrupted when a signal occurs. Lets demonstrate it through an example.


int flag;

void sig_handler(int signo)
   flag = 1;
   if (signo == SIGUSR1)
       printf("received SIGUSR1\n");
   else if (signo == SIGUSR2)
       printf("received SIGUSR2\n");
       printf("ERR : received signal %d\n", signo);

int main(void)
    if (signal(SIGUSR1, sig_handler) == SIG_ERR)
        printf("\ncan't catch SIGUSR1\n");
    if (signal(SIGUSR2, sig_handler) == SIG_ERR)
        printf("\ncan't catch SIGUSR2\n");

    /* Lets assume a logic consumes some processor time here*/

    /* now comes this while loop*/
    while(flag == 0)  // Simulate a dummy wait
        pause(); // Make this process to sleep until a signal occurs   (A slow system call :-) )

    return 0;
  • In the above piece of code, we have created a signal handler 'sig_handler()'.
  • We have used a flag 'flag' which is initialized as '0'.
  • In the main() function, the process is made to sleep by pause() system call.
  • The process is awakened only when a signal is received(property exhibited by pause() function).
  • Whenever a signal USR1 or USR2 occurs, the signal handler 'sig_handler()' gets called.
  • In the signal handler the flag 'flag' is set to one.
  • Since the process is awakened through a signal, the while loop executes once again
  • Since 'flag' is now '1', so pause() is not called and main() returns.
So, this was a demo code that relates the practical aspect of the concept told throughout this article.

But you might be thinking, what was so interesting in that?

Now, lets suppose that whomsoever wrote this code, wrote it with a precondition that when this code will run, once a signal USR1 will occur and this program will terminate after that. Note that the programmer knows that signal would occur only once and his/her program would catch it and return gracefully.

If you have a closer look at the logic, you will observe a small flaw in the program. The flaw can be exploited in the time window between when the while loop is called for the very first time and the pause() function is yet to be executed. Suppose, during this time gap, the long awaited :-) signal occurs. Ohh, did you guess what happens in this case? I'll tell you. In this case, before calling the pause() function, signal handler is called. Now, since the signal never occurs again, so the pause() system call never returns and hence the program is blocked for ever until its killed or system is taken down.

So, we see that programming with signals also required extreme care as we do not want our process to hang due to some loophole that the programmer left.


To conclude, the signals hold the capability of interrupting system calls that are working with slow devices like terminals. pipes etc. The application does not need to take care of this as POSIX compliant OSs allow the rescheduling of these system calls (internally) after the signal is handled.

Stay tuned for more
pradeep like this
kumkum01's Avatar, Join Date: Apr 2011
Go4Expert Member
Nice thread....Thanks for share useful information in this site...I really like this........
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Originally Posted by kumkum01 View Post
Nice thread....Thanks for share useful information in this site...I really like this........
But this is not a thread but an article.