- Signals Overview
- signal table
- signals sent
- signals received
- catching, masking, blocking
- /usr/include/signal.h
- Signal Table
- Processing with signals
- signal(SIGnum, myfunc) to set up entry in table, return value is ...
- When a SIGnum signal is received, consult table to get myfunc
- call myfunc as an interrupt service routine
- after myfunc return to next instruction
- Signal Table Values
- SIGINT 2 ^C typed usually sends SIGINT
- SIGQUIT 3 ^\ typed usually sends SIGQUIT
- SUREKILL 9 // can't be caught
- ps /kill combination
- SIG_DFL
- SIG_IGN
- Signal system call
#include
void (*signal(
int sig,
void (*function) (int))) (int);
When to catch signals?
- Example: graceful.c
#include
#include
main(){
int onint(); /* SIGINT handler */
int i;
signal(SIGINT, (void *) onint);
signal(SIGQUIT, (void *) onint);
for(i=0; ;i++)
fprintf(stdout,"%d\n",i);
}
int
onint(int sig){
fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig);
fprintf(stdout,"STDOUT:Recieved SIGNAL NUMBER =%d\n", sig);
/*
* Graceful exit type things removing temporary files etc.
*/
exit(1);
}
- The kill system Call - kill(pid_t pid, int sig)
- abort
- alarm(int n) - sends SIGALRM to self
- Setjmp, Longjmp
- Restarting on a signal (like vi, shell)
- Setjmp, Longjmp
- Example: shell0.c
#include
#include
#include
static jmp_buf restoreBuf; /* buffer for saving PC, SP etc. */
void fatal();
main(){
void onint(), onquit(); /* Signal handlers */
char buffer[1024];
int pid;
int jmpFlag;
signal(SIGINT, onint);
signal(SIGQUIT, onquit);
if((jmpFlag=setjmp(restoreBuf)) < 0) fatal(" setjmp error");
else if(jmpFlag != 0)
fprintf(stderr,"SIGINT received restoring registers\n");
printf("\nprompt: ");
while(gets(buffer) != NULL){ /* command loop */
if((pid = fork()) < 0) fatal("Fork error - too many processes");
else if (pid == 0){
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
execlp(buffer, buffer, NULL);
fprintf(stderr,"Command not Found\n");
exit(1);
} else (wait(0));
printf("\nprompt: ");
fflush(stdout);
}
}
void
onint(int sig){
fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig);
longjmp(restoreBuf,1);
fatal("longjmp returned\n");
}
void
onquit(int sig){
fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig);
exit(1);
}
void
fatal(char *s)
{
if(s) fprintf(stderr, "Fatal error: %s\n", s);
else fprintf(stderr, "\nStop.\n");
exit(1);
}
- Interrupting System Calls
- Slow system Calls
- Reentrant functions
- do not use heap or global data, everything on the stack
- cannot use stdio
- New Improved Signals
- sigactions replacing functions in table
- int sigaction(int sig, const struct sigaction *act, struct
sigaction *oact);
- man signal
- man 2 sigaction
- Review Signal Terminology
- generated
- delivered
- received
- blocked
- pending
- Signal sets
- int sigemptyset(sigset_t *set)
- int sigfillset(sigset_t *set)
- int sigaddset(sigset_t *set)
- int sigdelset(sigset_t *set)
- int sigismember(sigset_t *set)
- Possible macro definitions
#define sigemptyset(ptr) (*(ptr) = 0)
#define sigfillset(ptr) (*(ptr) = ~(sigset_t)0, 0)
/* Note comma operator above */
- int sigpending(sigset_t *set)
- sigaction(int sig, struct sigaction *act, struct sigaction *oldact)
- sigsetjmp and siglongjmp save and restore sigmask
- sigsetjmp and siglongjmp
- int str2sig(const char *str, int *signum); sig2str
- int sigsend(idtype_t idtype, id_t id, int sig);
- int sigprocmask(int cmd, const sigset_t *set, sigset_t *oset)
SIG_SETMASK
SIG_BLOCK
SIG_UNBLOCK
- Example: sigmask0.c
#include
#include
main() {
sigset_t sigset, oldset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
if(sigprocmask(SIG_SETMASK, &sigset, &oldset) < 0) {
fprintf(stderr, "sigprocmask ERROR\n");
exit(1);
}
if(sigismember(&sigset, SIGINT)) printf("SIGINT MASKED\n");
else printf("SIGINT NOT MASKED\n");
}
- sigmask1.c
#include
#include
main() {
sigset_t sigset, oldset, newset;
int pid;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
if(sigprocmask(SIG_SETMASK, &sigset, &oldset) < 0) fatal("sigprocmask");
if((pid = fork()) < 0) fatal("Fork failed");
else if (pid == 0) {
sleep(3);
if(sigpending(&newset)< 0) fatal("SIGpending");
if(sigismember(&newset,SIGINT))
printf("SIGINT signal is pending\n");
}else{
if(kill(pid, SIGINT)< 0) fatal("Fork failed"); /* sigsend on SUNs */
}
}
fatal(char *s) {
fprintf(stderr,"ERROR %s\n", s);
exit(1);
}