<<

System Programming Overview Signals 1. Definition 2. Signal Types 3. Generating a Signal 4. Responding to a Signal ™ Objectives 5. Common Uses of Signals – Introduce signals 6. Implementing a () – Concentrate on sigaction() function Timeout

continued 1730 UNIX System Programming: Signals Maria Hybinette 1 1730 UNIX System Programming: Signals Maria Hybinette 2

1. Definition 7. POSIX Signal Functions ™ A is an asynchronous which is 8. Interrupted System Calls delivered to a . 9. System Calls inside Handlers 10. More Information ™ Asynchronous means that the event can occur at any time – may be unrelated to the execution of the process – e.g. user types ctrl-C, or the modem hangs

1730 UNIX System Programming: Signals Maria Hybinette 3 1730 UNIX System Programming: Signals Maria Hybinette 4

2. Signal Types (31 in POSIX) Signal Sources terminal memory ™ Name Description Default Action driver management shell command SIGINT character typed terminate process SIGQUIT Quit character typed (^\) create core image SIGINT SIGHUP SIGKILL -9 terminate process SIGQUIT SIGSEGV Invalid memory reference create core image SIGKILL kernel SIGPIPE SIGPIPE on pipe but no reader terminate process SIGALRM alarm() clock ‘rings’ terminate process SIGUSR1 user-defined signal type terminate process SIGWINCH SIGALRM SIGUSR2 user-defined signal type terminate process window : manager a process SIGUSR1

™ See man 7 signal other user processes 1730 UNIX System Programming: Signals Maria Hybinette 5 1730 UNIX System Programming: Signals Maria Hybinette 6

UNIX: Signals Maria Hybinette 1 3. Generating a Signal kill()

™ Use the UNIX command: $ kill -KILL 4481 ™ Send a signal to a process (or group of processes). – send a SIGKILL signal to pid 4481 – check ™ #include ‹ ps –l kill( pid_t pid, int signo ); – to make sure process died

™ kill is not a good name; send_signal ™ Return 0 if ok, -1 on error. might be better.

1730 UNIX System Programming: Signals Maria Hybinette 7 1730 UNIX System Programming: Signals Maria Hybinette 8

4. Responding to a Signal Some pid Values ™ A process can: – ignore/discard the signal (not possible with ™ pid Meaning SIGKILL or SIGSTOP)

> 0 send signal to process pid – execute a signal handler function, and then possibly resume execution or terminate == 0 send signal to all processes whose ID – carry out the default action for that signal equals the sender’s pgid. e.g. parent kills all children ™ The choice is called the process’ signal disposition

1730 UNIX System Programming: Signals Maria Hybinette 9 1730 UNIX System Programming: Signals Maria Hybinette 10

signal(): call Actual Prototype ™ The actual prototype, listed in the “man” page is a bit ™ Specify a signal handler function to deal with a signal type. perplexing but is an expansion of the Sigfunc type:

™ #include void (*signal(int signo, void(*handler)(int)))(int); typedef void Sigfunc(int); /* my defn */ ™ In : Sigfunc *signal( int signo, Sigfunc *handler ); typedef void (*sighandler_t)(int);

– signal returns a pointer to a function that returns an int (i.e. it sig_handler_t signal(int signo, sighandler_t handler); returns a pointer to Sigfunc

™ Signal returns a pointer to a function that returns an int ™ Returns previous signal disposition if ok, SIG_ERR on error.

1730 UNIX System Programming: Signals Maria Hybinette 11 1730 UNIX System Programming: Signals Maria Hybinette 12

UNIX: Signals Maria Hybinette 2 The signal function itself returnsSignal a pointer toHandling a function. Example The return type is the same as the function that is passedThe signal in, toThe be handler function int main() { i.e.,™ aUse function the signal that handling takes caughtlibrary: an or ignored signal.hReceives a single integer signal( SIGINT, foo ); int and returns a void is given as argumentArgument and returns void : ™ Then can use the signal call: sig /* do usual things until SIGINT */ #include return 0; } void (*signal( int sig, void (*handler)(int))) (int) ; void foo( int signo ) ™ signal returns a pointer to the PREVIOUS signal { handler : /* deal with SIGINT signal */ The function to be called Signal™ #includeis a function when the specified signal that takestypedef two void Sigfunc(int); is /* received my defnThe */is returnedgiven as functiona return; /* return to program */ Sigfunc *signal( int signo, Sigfunc *handler ); } arguments: pointer totakes the function a integer sig and handler handler parameter.

1730 UNIX System Programming: Signals Maria Hybinette 13 1730 UNIX System Programming: Signals Maria Hybinette 14

sig_examp.c

#include #include : #include while(1) { void sig_usr( int signo ); /* handles two signals */ printf( “%2d\n“, I ); pause(); int main() { /* pause until signal handler int i = 0; * has processed signal */ if( signal( SIGUSR1,sig_usr ) == SIG_ERR ) i++; printf( “Cannot catch SIGUSR1\n” ); } if( signal( SIGUSR2,sig_usr ) == SIG_ERR ) return 0; printf(“Cannot catch SIGUSR2\n”); } :

continued continued 1730 UNIX System Programming: Signals Maria Hybinette 15 1730 UNIX System Programming: Signals Maria Hybinette 16

Usage void sig_usr( int signo ) /* argument is signal number */ { $ sig_examp & if( signo == SIGUSR1 ) [1] 4720 printf(“Received SIGUSR1\n”); 0 else if( signo == SIGUSR2 ) $ kill -USR1 4720 printf(“Received SIGUSR2\n”); Received SIGUSR1 else 1 printf(“Error: received signal $ kill -USR2 4720 %d\n”, signo); Received SIGUSR2 2 return; $ kill 4720 /* send SIGTERM */ } [1] + Terminated sig_examp & $ 1730 UNIX System Programming: Signals Maria Hybinette 17 1730 UNIX System Programming: Signals Maria Hybinette 18

UNIX: Signals Maria Hybinette 3 Special Sigfunc * Values Multiple Signals ™ If many signals of the same type are waiting ™ Value Meaning to be handled (e.g. two SIGINTs), then most UNIXs will only deliver one of them. SIG_IGN Ignore / discard the signal. SIG_IGN – the others are thrown away

SIG_DFL Use default action to handle signal.

SIG_ERR Returned by signal() as an error. ™ If many signals of different types are waiting to be handled (e.g. a SIGINT, SIGSEGV, SIGUSR1), they are not delivered in any fixed order.

1730 UNIX System Programming: Signals Maria Hybinette 19 1730 UNIX System Programming: Signals Maria Hybinette 20

pause() The Reset Problem ™ Suspend the calling process until a signal is caught. ™ In Linux (and many other UNIXs), the ™ #include signal disposition in a process is reset to its int pause(void); signal disposition in a process is reset to its default action immediately after the signal ™ Returns -1 with errno assigned EINTR. has been delivered. (Linux assigns it ERESTARTNOHAND).

™ pause() only returns after a signal handler has ™ Must call signal() again to reinstall the returned. signal handler function.

1730 UNIX System Programming: Signals Maria Hybinette 21 1730 UNIX System Programming: Signals Maria Hybinette 22

To keep catching Reset Problem the signal with this Reset Problem Example function, must call : the signal system int main() void ouch( int sig ) call again. { { signal(SIGINT, foo); printf( "OUCH! - I got signal %d\n", sig ); : (void) signal(SIGINT, ouch); /* do usual things until SIGINT */ } } Problem: from the time int main() that the interrupt function { starts to just before the void foo(int signo) signal handler is re-established (void) signal( SIGINT, ouch ); { the signal will not be while(1) handled. signal(SIGINT, foo); /* reinstall */ { : printf("Hello World!\n"); return; (1); If another SIGINT signal is } } received during this time, default behavior will be done, } 1730 UNIX System Programming: Signals Maria Hybinette 23 1730 UNIX System Programming: Signals Maria Hybinette i.e., program will terminate.24

UNIX: Signals Maria Hybinette 4 Re-installation may be too 5. Common Uses of slow! Signals ™ There is a (very) small time period in foo() 5.1. Ignore a Signal when a new SIGINT signal will cause the default action to be carried out -- process 5.2. Clean up and Terminate termination. 5.3. Dynamic Reconfiguration 5.4. Report Status ™ With signal() there is no answer to this problem. 5.5. Turn Debugging on/off – POSIX signal functions solve it (and some 5.6. Restore Previous Handler other later UNIXs)

1730 UNIX System Programming: Signals Maria Hybinette 25 1730 UNIX System Programming: Signals Maria Hybinette 26

5.2. Clean up and 5.1. Ignore a Signal Terminate : int main() : { /* global variables */ signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN); int my_children_pids; signal(SIGQUIT, SIG_IGN); : : /* do work without interruptions */ void clean_up(int signo); } int main() ™ Cannot ignore/handle SIGKILL or SIGSTOP { ™ Should check for SIG_ERR signal(SIGINT, clean_up); : } continued 1730 UNIX System Programming: Signals Maria Hybinette 27 1730 UNIX System} Programming: Signals Maria Hybinette 28

Problems void clean_up(int signo) { ™ If a program is run in the background then unlink(“/tmp/work-file”); the interrupt and quit signals (SIGINT, kill(my_children_pids, SIGTERM); SIGQUIT) are automatically ignored. ((int *)0); fprintf(stderr, “Program terminated\n”); ™ Your code should not override these (1); changes: } – check if the signal dispositions are SIG_IGN

1730 UNIX System Programming: Signals Maria Hybinette 29 1730 UNIX System Programming: Signals Maria Hybinette 30

UNIX: Signals Maria Hybinette 5 Checking the Disposition 5.3. Dynamic new disposition old disposition Reconfiguration

: : if( signal(SIGINT, SIG_IGN ) != SIG_IGN ) void read_config(int signo); signal(SIGINT, clean_up); int main() if( signal(SIGQUIT, SIG_IGN ) != SIG_IGN ) { signal(SIGQUIT, clean_up); read_config(0); /* dummy argument */ : while (1) /* work forever */ ™ Note: cannot check the signal disposition without } changing it (sigaction that we will look at later , is different) continued 1730 UNIX System Programming: Signals Maria Hybinette 31 1730 UNIX System Programming: Signals Maria Hybinette 32

void read_config(int signo) Problems { int fd;

signal( SIGHUP, read_config ); ™ Reset problem fd = open(“config_file”, O_RDONLY); /* read file and set global vars */ ™ Handler interruption (fd); – what is the effect of a SIGHUP in the middle of return; read_config()’s execution? } ™ Can only affect global variables.

1730 UNIX System Programming: Signals Maria Hybinette 33 1730 UNIX System Programming: Signals Maria Hybinette 34

void print_status(int signo) 5.4. Report Status { signal(SIGUSR1, print_status); : signal(SIGUSR1, print_status); void print_status(int signo); printf(“%d blocks copied\n”, count); int count; /* global */ return; } int main() { signal(SIGUSR1, print_status); : ™ Reset problem for( count=0; count < BIG_NUM; count++ ) ™ count value not always defined. { /* read block from tape */ ™ Must use global variables for status information /* write block to disk */ } ... } continued 1730 UNIX System Programming: Signals Maria Hybinette 35 1730 UNIX System Programming: Signals Maria Hybinette 36

UNIX: Signals Maria Hybinette 6 5.5. Turn Debugging on/off

: void toggle_debug(int signo); void toggle_debug(int signo) { int debug = 0; /* initialize here */ signal(SIGUSR2, toggle_debug); int main() { debug = ((debug == 1) ? 0 : 1); signal(SIGUSR2, toggle_debug); return; /* do work */ } if (debug == 1) printf(“...”); ... continued 1730 UNIX} System Programming: Signals Maria Hybinette 37 1730 UNIX System Programming: Signals Maria Hybinette 38

5.6. Restore Previous 6. Implementing a read() Handler Timeout : ™ Put an upper limit on an operation that Sigfunc *old_hand; Put an upper limit on an operation that might block forever /* set action for SIGTERM; – e.g. read() save old handler */ old_hand = signal(SIGTERM, foobar); ™ 6.1. alarm() /* do work */ 6.2. Bad read() Timeout /* restore old handler */ 6.3. setjmp() and longjmp() signal(SIGTERM, old_hand); 6.4. Better read() Timeout :

1730 UNIX System Programming: Signals Maria Hybinette 39 1730 UNIX System Programming: Signals Maria Hybinette 40

6.1. alarm() Some Tricky Aspects ™ A process can have at most one alarm timer ™ Set an alarm timer that will ‘ring’ after a running at once. specified number of seconds – a signal is generated – a SIGALRM signal is generated ™ If alarm() is called when there is an existing alarm set then it returns the number ™ #include of seconds remaining for the old alarm, and long alarm(long secs); sets the timer to the new alarm value. – What do we do with the “old alarm value”? ™ Returns 0 or number of seconds until previously set alarm would have ‘rung’. ™ An alarm(0) call causes the previous alarm to be cancelled. 1730 UNIX System Programming: Signals Maria Hybinette 41 1730 UNIX System Programming: Signals Maria Hybinette 42

UNIX: Signals Maria Hybinette 7 if( signal(SIGALRM, sig_alrm) == SIG_ERR ) 6.2. Bad read() Timeout { printf(“signal(SIGALRM) error\n”); #include exit(1); #include } #include alarm(10); #define MAXLINE 512 n = read( 0, line, MAXLINE ); alarm(0); void sig_alrm( int signo ); if( n < 0 ) /* read error */ int main() fprintf( stderr, “\nread error\n” ); { else int n; write( 1, line, n ); char line[MAXLINE]; return 0; : } continued continued 1730 UNIX System Programming: Signals Maria Hybinette 43 1730 UNIX System Programming: Signals Maria Hybinette 44

Problems ™ The code assumes that the read() call terminates with an error after being interrupted ( talk about void sig_alrm(int signo) this later). /* do nothing, just handle signal */ { ™ Race Conditon: The kernel may take longer than return; 10 seconds to start the read() after the alarm() } call. – the alarm may ‘ring’ before the read() starts – then the read() is not being timed; may block forever – Two ways two solve this one uses setjmp and the other uses sigprocmask and sigsuspend

1730 UNIX System Programming: Signals Maria Hybinette 45 1730 UNIX System Programming: Signals Maria Hybinette 46

6.3. setjmp() and longjmp() Prototypes

™ In C we cannot use goto to jump to a label in ™ #include another function int setjmp( jmp_buf env ); – use setjmp() and longjmp() for those ‘long jumps’ ™ Returns 0 if called directly, non-zero if returning from a call to longjmp(). ™ Only uses which are good style: – error handling which requires a deeply nested function to recover to a higher level (e.g. back to main()) ™ #include void longjmp( jmp_buf env, int val ); – coding timeouts with signals

1730 UNIX System Programming: Signals Maria Hybinette 47 1730 UNIX System Programming: Signals Maria Hybinette 48

UNIX: Signals Maria Hybinette 8 Example Behavior : jmp_buf env; /* global */ ™ In the setjmp() call, env is initialized to information about the current state of the int main() { stack. char line[MAX]; int errval;

™ The longjmp() call causes the stack to be if(( errval = setjmp(env) ) != 0 ) printf( “error %d: restart\n”, errval ); reset to its env value. while( fgets( line, MAX, stdin ) != NULL ) process_line(line); ™ Execution restarts after the setjmp() call, return 0; } but this time setjmp() returns val. continued 1730 UNIX System Programming: Signals Maria Hybinette 49 1730 UNIX System Programming: Signals Maria Hybinette 50

: void process_line( char * ptr ) { : Stack Frames at setjmp() cmd_add() : } top of stack void cmd_add() main() { int token; stack frame token = get_token(); setjmp(env) if( token < 0 ) /* bad error */ longjmp( env, 1 ); returns 0; env records stack /* normal processing */ direction of } stack growth frames info int get_token() { if( some error ) longjmp( env, 2 ); }

1730 UNIX System Programming: Signals Maria Hybinette 51 1730 UNIX System Programming: Signals Maria Hybinette 52

Stack Frames at longjmp() sleep1() #include #include top of stack main() void sig_alrm( int signo ) stack frame { return; /* return to wake up pause */ process_line() } stack frame unsigned int sleep1( unsigned int nsecs ) direction of { stack growth : if( signal( SIGALRM, sig_alrm ) == SIG_ERR ) : return (nsecs); longjmp(env,1) alarm( nsecs ); /* starts timer */ cmd_add() causes stack frames pause(); /* next caugt signal wakes */ stack frame return( alarm( 0 ) ); /* turn off timer, return unslept to be reset * time */ } 1730 UNIX System Programming: Signals Maria Hybinette 53 1730 UNIX System Programming: Signals Maria Hybinette 54

UNIX: Signals Maria Hybinette 9 sleep2() Sleep1 and Sleep2 static void jmp_buf env_alrm; ™ Sleep2 fixes . Even if the void sig_alrm( int signo ) { pause is never executed. longjmp( env_alrm, 1 ); } unsigned int sleep2( unsigned int nsecs ) ™ There is one more problem (will talk about { if( signal( SIGALRM, sig_alrm ) == SIG_ERR ) that after “fixing the earlier read function”) return (nsecs); if( setjmp( env_alrm) == 0 ) { alarm( nsecs ); /* starts timer */ pause(); /* next caugt signal wakes } return( alarm( 0 ) ); continued 1730 UNIX System} Programming: Signals Maria Hybinette 55 1730 UNIX System Programming: Signals Maria Hybinette 56

Status of Variables? 6.4. Better read() Timeout

™ The POSIX standard says: #include – global and static variable values will not be #include #include changed by the longjmp() call #include

™ Nothing is specified about local variables, #define MAXLINE 512 void sig_alrm( int signo ); are they “rolled back” to their original jmp_buf env_alrm; values (at the setjmp call) as the stack”? – they may be restored to their values at the first int main() setjmp(), but maybe not { int n; setjmp() char line[MAXLINE]; ‹ Most implementations do not roll back their values : continued 1730 UNIX System Programming: Signals Maria Hybinette 57 1730 UNIX System Programming: Signals Maria Hybinette 58

if( signal(SIGALRM, sig_alrm) == SIG_ERR) { printf(“signal(SIGALRM) error\n”); exit(1); : } if( n < 0 ) /* read error */ fprintf( stderr, “\nread error\n” ); if( setjmp(env_alrm) != 0 ) else { write( 1, line, n ); fprintf(stderr, “\nread() too slow\n”); return 0; exit(2); } }

alarm(10); n = read(0, line, MAXLINE); alarm(0); : continued continued 1730 UNIX System Programming: Signals Maria Hybinette 59 1730 UNIX System Programming: Signals Maria Hybinette 60

UNIX: Signals Maria Hybinette 10 Caveat: Non-local Jumps

void sig_alrm(int signo) From the UNIX man pages: /* interrupt the read() and jump to setjmp() call with value 1 */ WARNINGS If longjmp() or siglongjmp() are called even though env was { never primed by a call to setjmp() or sigsetjmp(), or when longjmp(env_alrm, 1); the last such call was in a function that has since } returned, absolute chaos is guaranteed.

1730 UNIX System Programming: Signals Maria Hybinette 61 1730 UNIX System Programming: Signals Maria Hybinette 62

A Problem Remains! 7. POSIX Signal Functions

™ If the program has several signal handlers ™ The POSIX signal functions can control then: signals in more ways: – execution might be inside one when an alarm ‘rings’ – can block signals for a while, and deliver them later (good for coding critical sections) – the longjmp() call will jump to the location, and abort the other setjmp() location, and abort the other – can switch off the resetting of the signal signal handler -- might lose / corrupt data disposition when a handler is called (no reset problem)

1730 UNIX System Programming: Signals Maria Hybinette 63 1730 UNIX System Programming: Signals Maria Hybinette 64

7.1. Signal Sets

™ The POSIX signal system, uses signal sets, to ™ The signal set stores collections of signal deal with pending signals that might otherwise types. be missed while a signal is being processed ™ Sets are used by signal functions to define which signal types are to be processed.

™ POSIX contains several functions for creating, changing and examining signal sets.

1730 UNIX System Programming: Signals Maria Hybinette 65 1730 UNIX System Programming: Signals Maria Hybinette 66

UNIX: Signals Maria Hybinette 11 Prototypes 7.2. sigprocmask()

™ #include ™ A process uses a signal set to create a mask int sigemptyset( sigset_t *set ); which defines the signals it is blocking from int sigfillset( sigset_t *set ); delivery. – good for critical sections where you want to block certain signals. int sigaddset( sigset_t *set, int signo ); int sigdelset( sigset_t *set, int signo ); ™ #include int sigismember( const sigset_t *set, int sigprocmask( int how, int signo ); const sigset_t *set, sigset_t *oldset); ™ how – indicates how mask is modified

1730 UNIX System Programming: Signals Maria Hybinette 67 1730 UNIX System Programming: Signals Maria Hybinette 68

how Meanings A Critical Code Region : ™ Value Meaning sigset_t newmask, oldmask;

sigemptyset( &newmask ); SIG_BLOCK set signals are added to mask sigaddset( &newmask, SIGINT );

SIG_UNBLOCK set signals are removed from mask /* block SIGINT; save old mask */ sigprocmask( SIG_BLOCK, &newmask, &oldmask ); SIG_SETMASK set becomes new mask /* critical region of code */

/* reset mask which unblocks SIGINT */ sigprocmask( SIG_SETMASK, &oldmask, NULL ); : 1730 UNIX System Programming: Signals Maria Hybinette 69 1730 UNIX System Programming: Signals Maria Hybinette 70

7.3. sigaction() sigaction Structure

struct sigaction { ™ Supercedes (more powerful than) signal() void (*sa_handler)( int ); /* action to be taken or SIG_IGN, SIG_DFL */ – sigaction() can be used to code a non- sigset_t sa_mask; /* additional signal to be blocked */ resetting signal() int sa_flags; /* modifies action of the signal */ void (*sa_sigaction)( int, siginfo_t *, void * );

} ™ #include ™ sa_flags – int sigaction(int signo, – SIG_DFL reset handler to default upon return – SA_SIGINFO denotes extra information is passed to handler (.i.e. specifies the const struct sigaction *act, use of the “second” handler in the structure. struct sigaction *oldact );

1730 UNIX System Programming: Signals Maria Hybinette 71 1730 UNIX System Programming: Signals Maria Hybinette 72

UNIX: Signals Maria Hybinette 12 Signal Raising struct sigaction sigaction() Behavior { int main() void (*) (int) sa_handler { sigset_t sa_mask int sa_flags struct sigaction act; ™ A signo signal causes the sa_handler signal }

handler to be called. act.sa_handler = ouch;

sigemptyset( &act.sa_mask ); ™ While sa_handler executes, the signals in Set the signal handler to sa_mask are blocked. Any more signo signals are act.sa_flags = 0; be the function ouch also blocked. sigaction( SIGINT, &act, 0 No); flags are needed here. We can manipulate Possible flags include: while(1) SA_NOCLDSTOP ™ sets of signals.. ™ sa_handler remains installed until it is changed by { SA_RESETHAND another sigaction() call. No reset problem. printf("Hello World!\n");SA_RESTART sleep(1); This call setsSA_NODEFER the signal } handler for the SIGINT (ctrl-C) signal 1730 UNIX System Programming: Signals Maria Hybinette 73 1730 UNIX System} Programming: Signals Maria Hybinette 74

Signal Raising sigexPOS.c /* sigexPOS.c - demonstrate sigaction() */ /* include files as before */ ™ This function will continually capture the ctrl-C (SIGINT) signal. int main(void) { /* struct to deal with action on signal set */ ™ Default behavior is not restored after signal static struct sigaction act; is caught. void catchint(int); /* user signal handler */

™To terminate the program, must type ctrl-\, /* set up action to take on receipt of SIGINT */ the SIGQUIT signal. act.sa_handler = catchint;

1730 UNIX System Programming: Signals Maria Hybinette 75 1730 UNIX System Programming: Signals Maria Hybinette 76

/* create full set of signals */ Signals - Ignoring signals sigfillset(&(act.sa_mask)); ™ Other than SIGKILL and SIGSTOP, signals can be /* before sigaction call, SIGINT will terminate ignored: * process */

™ Instead of in the previous program: /* now, SIGINT will cause catchint to be executed */ sigaction( SIGINT, &act, NULL ); sigaction( SIGQUIT, &act, NULL ); act.sa_handler = catchint /* or whatever */ We use: printf("sleep call #1\n"); act.sa_handler = SIG_IGN; sleep(1); The ^C key will be ignored /* rest of program as before */

1730 UNIX System Programming: Signals Maria Hybinette 77 1730 UNIX System Programming: Signals Maria Hybinette 78

UNIX: Signals Maria Hybinette 13 Restoring previous action A Basic signal()

#include ™ The third parameter to sigaction, oact, can be used: Sigfunc *signal( int signo, Sigfunc *func ) { /* save old action */ struct sigaction act, oact; sigaction( SIGTERM, NULL, &oact ); act.sa_handler = func; sigemptyset( &act.sa_mask ); /* set new action */ act.sa_flags = 0;

act.sa_handler = SIG_IGN; act.sa_flags |= SA_INTERRUPT; if( signo != SIGALRM ) sigaction( SIGTERM, &act, NULL ); act.sa_flags |= SA_RESTART; /* any interrupted by a signal * other than alarm is restarted */ /* restore old action */ if( sigaction( signo, &act, &oact) < 0 ) sigaction( SIGTERM, &oact, NULL ); return(SIG_ERR); return( oact.sa_handler ); } 1730 UNIX System Programming: Signals Maria Hybinette 79 1730 UNIX System Programming: Signals Maria Hybinette 80

7.4. Other POSIX [sig]longjmp & [sig]setjmp Functions

™ sigpending() examine blocked signals NOTES (longjmp, sigjmp) POSIX does not specify whether longjmp will restore the signal context. If you want to save and restore signal ™ sigsetjmp() masks, use siglongjmp. siglongjmp() jump functions for use in signal handlers which NOTES (setjmp, sigjmp) handle masks correctly POSIX does not specify whether setjmp will save the signal context. (In SYSV it will not. In BSD4.3 it will, and there is a function _setjmp that will not.) If you want ™ sigsuspend() atomically reset mask to save signal masks, use sigsetjmp. and sleep

1730 UNIX System Programming: Signals Maria Hybinette 81 1730 UNIX System Programming: Signals Maria Hybinette 82

Example 8. Interrupted System Calls #include … 8. Interrupted System Calls #include while(1) #include { sleep(5); sigjmp_buf buf; printf(“ waiting...\n"); ™ } ™ When a system call (e.g. read()) is interrupted by void handler(int sig) } a signal, a signal handler is called, returns, and { siglongjmp(buf, 1); then what? } > a.out starting main() waiting... { waiting... ™ Control-c On many UNIXs, slow system function calls do signal(SIGINT, handler); restarting waiting... not resume. Instead they return an error and errno if( sigsetjmp(buf, 1) == 0 ) waiting... is assigned EINTR. printf("starting\n"); waiting... else restarting Control-c – true of Linux, but can be altered with (Linux-specific) waiting... printf("restarting\n") restarting Control-c siginterrupt() ; waiting... … waiting... 1730 UNIX System Programming: Signals Maria Hybinette 83 1730 UNIX System Programming: Signals Maria Hybinette 84

UNIX: Signals Maria Hybinette 14 Slow System Functions Non-slow System Functions

™ Slow system functions carry out I/O on ™ Most system functions are non-slow, including things that can possibly block the caller ones that do disk I/O forever: – e.g. read() of a disk file – read() is sometimes a slow function, sometimes not – pipes, terminal drivers, networks

– some IPC functions ™ Some UNIXs resume non-slow system functions – pause(), some uses of ioctl() after the handler has finished.

™ Can use signals on slow system functions to ™ Some UNIXs only call the handler after the non- code up timeouts (e.g. did earlier ) slow system function call has finished. 1730 UNIX System Programming: Signals Maria Hybinette 85 1730 UNIX System Programming: Signals Maria Hybinette 86

9. System Calls inside Non-reentrant Functions Handlers

™ If a system function is called inside a signal ™ A functions may be non-reentrant (only one call handler then it may interact with an interrupted to it at once) for a number of reasons: call to the same function in the main code. – it uses a static data structure – e.g. malloc() – it manipulates the heap: malloc(), free(), etc. ™ This is not a problem if the function is reentrant – a process can contain multiple calls to these functions at – it uses the standard I/O library the same time ‹ e,g, scanf(), printf() – e.g. read(), write(), fork(), many more ‹ the library uses global data structures in a non-reentrant way

1730 UNIX System Programming: Signals Maria Hybinette 87 1730 UNIX System Programming: Signals Maria Hybinette 88

errno Problem

™ errno is usually represented by a global variable.

™ Its value in the program can be changed suddenly by a signal handler which produces a new system function error.

1730 UNIX System Programming: Signals Maria Hybinette 89

UNIX: Signals Maria Hybinette 15