Ch. 13 Synchronisation and State
Reentrancy - function’s capability to work correctly, even when it’s interrupted by another running thread that calls the same function. It must not modify any global vars or shared resources w/o adequate locking.
In race conditions outcome of an operation is successful only if certain resources are acted on in an expected order.
Starvation and deadlocks
Starvation - a thread never receives ownership of a synchronisation object.
Deadlocks can occur when several thread are using multiple sync objects at once but in a different order. For a deadlock to be possible, 4 conditions are required: mutual exclusion, hold and wait, no preemption, circular wait
semget() - create a new semaphore set or obtain an existing set
semop() - performs operations on selected semaphores in a set
semctl() - perform a control operation on a selected semaphore
- Synch objects required but not used, e.g. when 2 processes are attempting to access a shared resource
- Incorrect use (Windows)
- Squatting with named synchronisation objects (Windows)
- Synchronisation objects scoreboard
- Lock matching
- Ignore the signal (apart from SIGKILL and SIGSTOP)
- Block the signal (same exception)
- Install a signal handler
signal() for installing a handler
sigaction() interface - more detailed attributes for handled signals
setjmp(), longjmp(), sigsetjmp(), siglongjmp() often used in signal-handling routines to return to a certain location in the program in order to continue processing after a signal has been caught. Program context of setjmp() is restored when returned from longjmp(). Zero return value means a call to setjmp, a non-zero value indicates a return from a longjmp
Problem when the handler relies on some sort of global program state, such as assumption that global variables are initialised when in fact they aren’t.
Various problems (non-asynchronous-safe state) may arise from attempting to restart execution using longjmp() function in non-returning signal handlers.
Other problems can be caused by invalid longjmp targets. The function that call setjmp or sigsetjmp must be still on the runtime exec stack whenever longjmp or siglongjmp are called. If the original function has terminated, the pointer will be invalid.
Pay special attention for the following reasons:
- The signal handler doesn’t return, so it’s highly unlikely that it will be asynchronous safe unless it exits immediately.
- It might be possible to find a code path where the function that did the setjmp returns, but the signal handler with the longjmp is not removed.
- The signal mask might have changed, which could be an issue if sigsetjmp and siglongjmp aren’t used. If they are, does restoring the old signal mask cause problems as well?
- Permissions might have changed.
- Program state might have changed such that the state of variable that are valid when 8setjmp* is originally called but not necessarily when longjmp is called.
Sometimes non-async safe functions are used in signal handlers (see signal(3) or sigaction(2))
Signal handlers using longjmp and siglongjmp are practically guaranteed to be non-async safe unless they jump to a location that immediately exits.
<skipped> - Critical sections
- Race conditions occurs when the successful outcome of an operation depends on whether the threads are scheduled for running in a certain order.
- Identify shared resources that are acted on by multiple threads.
- Determine whether the appropriate locking mechanism has been selected. There are specific rules in the book for different types of resources.
- Examine the code that modifies this resource to see whether appropriate locking mechanisms have been neglected or misused.
- Deadlocks and starvation