How to handle Control-C signal while designing a shell?
Jonathan Leffler provided helpful hints (though not sufficient, at least on some popular operating system):
- Look at what
scanf()
returns. - Don't use
loop()
in the signal handler - Don't use
signal()
— usesigaction()
. In your case, this has two advantages:- Restoring the signal action to the default state on call of the signal handler can be avoided, so you don't have to change the action again in the handler.
- Restarting the
read()
system call (insidescanf()
) can be avoided, so thatscanf()
returns and you can react to the interrupt in the first place.
So, the signal handler can be just
void sigintHandler(int sig_num){ printf("\n"); // or perhaps better write(1, "\n", 1)}
The signal(SIGINT, sigintHandler);
in main()
can be replaced with
sigaction(SIGINT, &(struct sigaction){ .sa_handler = sigintHandler }, NULL);
and the scanf("%s",a);
with
if (scanf("%s", a) == EOF) { if (errno == EINTR) continue; // read operation interrupted by signal return; }
EOF is returned on interrupt as well as on end of file, so the cases are to be distinguished through errno
. Besides, it's nice if your program provides a way to exit it, thus the return
.