Signals & Sessions 4



Unix Internals

4

Signals & Sessions

Signals

• notifying processes of system events

• primitive communication & synchronization between user processes

• SVR2 inherently unreliable and defective signaling mechanism

• 4.3BSD robust signal mechanism; incompatible with SV interface

• POSIX 1003.1 Standard defines standard interface but does not regulate implementation

• SVR4 implemented POSIX-compliant signal system;

o incorporated many features of BSD;

o backward compatible with earlier SV releases

Signal Generation & Handling

• event occurs that requires process be notified;

• event is delivered when

o target process recognizes its arrival and

o takes appropriate action

• after event is delivered and before it is delivered is pending to the process

• mapping of signals to signal numbers is different between SV and BSD

• systems may contain more than the POSIX mandated minimum 31 signals

signal handling

default actions

• abort

o generates core dump

▪ writes process address space & register content to core file

o terminates process

• exit -- terminate process

• ignore -- ignore signal

• stop -- suspends process

• continue -- resumes process

signal handler actions

▪ block – signal will not be delivered until it is unblocked

▪ reset action to default

▪ specify a special signal handler function

receiving process becomes aware of signal when kernel calls issig() on behalf of the process to check for pending signals

▪ kernel calls issig() only

o before returning to user mode from system call or interrupt

o before blocking on interruptable event

o after waking up from interruptable event

▪ if iisig() returns TRUE, kernel calls psig() to dispatch signal

▪ psig()

o terminates process, generating core dump if required, or

o calls sendsig() to invoke user-defined signal handler

▪ sendsig()

■ returns process to user mode,

■ transfers control to signal handler, &

■ arranges for the process to resume the interrupted code after the handler completes.

▪ signal handler completes (process resumes from point of interruption

▪ if signal arrived while process was executing a system call,

kernel usually aborts the call & returns the EINTR error code

▪ 4.2BSD allows restarting of selected system calls, 4.3BSD provides siginterrupt call that disables restart on per-signal basis

signal generation -- sources

▪ exceptions ( kernel notifies process that created the event

▪ process ( kill() or sigsend() signal from sending process

to receiving process or to set of receiving processes

▪ terminal ( keyboard interrupts, e.g., ^c or ^\, signal sent

to foreground processes on that terminal;

stty allows user to bind terminal-generated

signals to specific key

▪ job control ( signal sent to background processes that

attempt to read &/or write to the terminal;

kernel notifies parent of child termination via signal

▪ quotas ( signal sent for exceeding CPU or file size limits

▪ notifications ( process requests notification of certain events,

e.g., I/O device ready

▪ alarms ( process sets alarm; kernel send expiration signal

o ITIMER_REAL measures clock time; generates SIGALRM signal

o ITIMER_VIRTUAL measures virtual time, i.e., user mode time;

generates SIGVALRM signal

o ITIMER_PROF measures total time used by the process;

generates SIGPROF signal

■►

(

uninterruptible sleep

▪ sleeping for a short event, e.g., disk I/O

▪ cannot be disturbed by signal

interruptable sleep

▪ sleeping for an indefinite period of time, e.g., terminal I/O

▪ may be woken up if signal occurs

Unreliable Signals

SVR2 implementation of signals was unreliable and defective

▪ Signal handlers

o are not persistent

o do not mask recurring instances of the same signal

o race condition – window of vulnerability -- time it takes to reinstall the signal handler after it is invoked

o signal disposition information is stored in the u_signal array in the u area which contains one entry for each signal type

■ user-defined handler

■ SIG_DFL – use default action

■ SIG_IGN – ignore signal

▪ kernel

o can only access the u area of the current process

o has no way of knowing how another process will deal with the signal

Reliable Signal Features

▪ persistent handlers

signal handlers remain installed until explicitly uninstalled

▪ masking

if blocked signal is generated, kernel retains signal but does not post it to the process; when process unblocks signal, kernel posts signal

▪ sleeping processes

signal disposition information is stored in proc structure

(always visible to kernel)

rather than the u area

( only the current process is visible)

if kernel generates signal for process in an interruptible sleep, but

process is ignoring or blocking the signal, kernel need not wake the process

▪ unblock & wait

o pause() blocks process until signal arrives

o sigpause() atomically unmasks the signal & blocks the process until signal is received;

o if unmasked signal is pending when signal call is issued, call returns immediately

SVR3 Implementation

▪ sighold() ( block single signal

▪ sigrelse() ( unblock single signal

▪ sigpause() ( atomically unblocks single signal & pauses process

▪ sigset() ( specifies persistent handler

▪ deficiencies: handles only single signals

BSD Signal Management

sigsetmask() ( specifies signal set to be blocked

sigblock() ( adds additional signals to signal set

sigpause() ( atomically installs new mask of blocked signals &

pauses the process

sigvec() ( installs a signal handler for a single signal;

specifies mask to be associated with signal;

when signal is generated, prior to calling handler,

kernel will install new mask of blocked signals

that is the union of the current mask, the mask

specified by sigvec() and the current signal

SVR4 Signals

▪ sigprocmask( how, setp, osetp ); ( modify signal set mask

o how

▪ SIG_BLOCK ( bitwise_or (setp, existing mask)

(setp signals are added to existing mask

▪ SIG_UNBLOCK ( bitwise_or ((not(setp), existing mask)

(setp signals removed from the existing mask

▪ SIG_SETMASK ( current mask replaced by setp

o osetp contains mask prior to modification

▪ sigaltstack( stack, old_stack ); ( specify signal handler stack

▪ sigsuspend (sigmask); ( sets blocked signals mask to

sigmask; pauses process;

if changing mask unblocks

signal, call returns immediately

▪ sigpending (setp); ( returns signal set pending to process

▪ sigsendset (procset, sig); ( send signal sig to process set that is

specified by procset

▪ sigaction (signo, act, oact); ( specifies handler for signal signo;

o act points to sigaction structure that contains signal disposition, i.e.,

SIG-IGN, SIG_DFL, handler address;

o mask associated with the signal,

o flags

▪ SA_NOCLDSTOP (do not generate SIGCHLD when child is suspended

▪ SA_RESTART (restart system call if interrupted by this signal

▪ SA_ONSTACK (handle this signal on alternate stack

▪ SA_NOCLDWAIT (do not create zombies

▪ SA_SIGINFO (provide additional information to signal handler

▪ SA_NODEFER (do not automatically block this signal while

its handler is running

▪ SA_RESETHAND (reset action to default before calling the handler

signal implementation

u area -- information to properly invoke signal handlers

u_signal[] vector of signal handlers for each signal

u_sigmask[] signal masks associated with each handler

u_sigaltstack pointer to alternate signal stack

u_sigonstack mask of signals to handle on alternate stack

u_oldsig set of handlers that must exhibit unreliable behavior

proc_structure -- information relating to generation and posting of signals

p_cursig signal currently being handled

p_sig pending signals mask

p_hold blocked signals mask

p_ignore ignored signals mask

signal generation, delivery & handling

• signal generated ( kernel checks the proc structure of receiving process

o if signal is to be ignored then kernel returns without taking action

else

kernel adds the signal to p_cursig, the pending signals bitmask

• p_cursig is a bitmask with one bit per signal (

kernel can record only one instance of each signal

• if process is in interruptible sleep & signal is not blocked then the kernel awakens the process so that it can receive & handle the signal

• job control signal SIGSTOP directly suspends the process

• job control signal SIGCONT directly resumes the process

• process checks for signals, i.e., kernel calls issig(), when process

o is about to return from kernel mode after system call or interrupt

o before entering, or after awakening from, an interruptible sleep

• issig() looks for bits set in the p_cursig bitmask

o if any bit is set, issig() checks p_hold to see if the signal is blocked

o if it is not blocked

issig() stores the signals number in p_sig and returns TRUE

o if the signal is pending, kernel calls psig()

psig() inspects the u_area pertaining to the signal

• if no handler is declared, psig() takes the default action

• if handler is declared,

psig()

• alters p_hold, the mask of blocked signals,

• adds the current signal to p_hold

• adds any signal specified in u_sigmask

associated with this signal

• calls sendsig()

sendsig()

• arranges for process to return to user mode

• pass control to handler

• ensures that when handler completes, process will resume at point where it was executing prior to receiving signal

exceptions

• exception ( trap ( signal notification

• signal action

o default – terminate process

o invoke signal handler

• ADA implements a library of default handlers

• debuggers – generate exceptions at breakpoints

• drawbacks

o signal handler runs in same context as exception

o single thread deals with the

• context of the exception

• context of the handler

o kernel passes some of the exception context to the handler

o handler cannot access full register context at the time of exception

o signals are designed for single threaded processes

Mach Exception Handling

victim thread

• raises the exception, sends IPC message

notifying kernel of exception occurrence

• waits for exception handling to complete

handler thread

• receives notification from kernel via IPC message

which contains both the victim identity & exception type

• handles exception ( sends exception clear message to victim thread

( victim thread resumes execution

• cannot handle exception ( sends message to kernel

( kernel terminates victim thread

exception ports

• port – protected message queue

• one port assigned to each task;

only that task can receive messages from that port

• one port assigned to each thread in the task;

only that thread can receive messages from that port

• many tasks can have send rights to a given port

• error handlers are associated with threads

o each thread may have a different error handler

o handler’s port is registered as the thread’s exception port

o new thread created ( exception port initialized to NULL ( no error handler

• debugger attaches to task (( register debugger port as task’s exception port

o debugger runs as separate task

o debugger has receive rights to target tasks exception port

o each task inherits its exception port from its parent

( debuggers control all descendents of target task

• thread exception port used for error handlers that are transparent to debuggers

• if error handler is installed, Mach invokes it in preference to the debugger

• exception occurs

o exception sent to thread exception port

( exceptions that evoke error handlers are not seen by debugger

o if thread error handler cannot clear the exception,

exception is sent to task exception port

o if task exception handler cannot clear exception,

kernel terminates the victim thread

error handling

• victim thread raises exception

• initial message (sent to exception port) contains

o reply port

o victim thread identity

o originating task identity

o exception type

• handler

o processes exception

o sends message to reply port

• victim thread receives reply message & resumes normal execution

• exception occurs for which a Unix signal handler is installed

( message sent to special system-invoked handler

( system-invoked handler

• modifies victim thread such that the signal handler is executed when victim thread resumes

• clears exception

• causes victim thread to execute

debugger interactions

analysis

< to be supplied later, see page 99>

Process Groups & Terminal Management

process groups

• each process belongs to a process group

• process group ID

• process is a group leader (( PID == process group ID

• a process inherits its process group ID from its parent process

• all processes in a group are descendents of the group leader

controlling terminal

• a process may have a controlling terminal

• a process may exist without a controlling terminal

• the controlling terminal is usually the login terminal

at which the process was created

• all processes in a group share the same controlling terminal

• special file /dev/tty

o associated with the controlling terminal of each process

o file device driver routes all requests to the appropriate terminal

o 4.3 BSD

▪ device number of controlling terminal

is stored in the u_ttyd field of the u area

▪ terminal read command

(*cdevsw[major(u.u_ttyd)].d_read) (u.u_ttyd, flags);

controlling group

• each terminal is associated with a process group

• terminal’s controlling group is identified by the

t_pgrp field in the tty structure (device driver)

• keyboard generated signals are sent to

all processes in the terminals’s controlling group, i.e.,

all processes such that p_pgrp == t_pgrp

job control (4BSD SVR4)

• suspend/resume process group

• control process group’s access to the terminal

• job control shell – csh, ksh -- control characters and shell commands

SVR3 Model

process groups

• process group exhibits the characteristics of a terminal login session

• fork() – child process inherits the parents process group ID

• setgrp() – sets caller’s group ID equal to its PID

controlling terminal

• terminal is owned by it’s controlling group

• setgrp() ( group ID == PID ( process losses its controlling terminal

o first terminal that process opens, which is not already a controlling terminal, becomes its controlling terminal, i.e., terminal t_pgrp set to p_prgp of process

o all child processes inherit controlling terminal from the group leader

• no two process groups have the same controlling terminal

typical scenario

• init process creates a new child for each terminal listed in /etc/inittab file

• child process

o calls setgrp() which makes the child process a group leader

o calls exec() function to initiate the getty() program;

getty() displays the login prompt

• user enters login name ( getty execs the login program

• login program

o requests and verifies password

o execs the login shell

• login shell is

o direct child of init

o process group leader

• system daemons started from within a login session

create their own process groups

terminal access

• no support for job control

• all process that have opened a terminal can access it equally, regardless of whether they are in the foreground or background

• concurrent writes -- output randomly intermingled on the screen

• concurrent reads -- input randomly intermingled to the various processes

terminal signals

• keyboard generated signals, e.g., SIGQUIT, SIGINT, are sent to all processes in the terminal’s controlling group

• shell creates background processes ( sets them to ignore keyboard signals

• redirects stdin to /dev/null, i.e., cannot read from stdin, i.e., keyboard

detaching terminal

• terminal detached from controlling group (( t_prgp == 0

o no processes have the terminal open

o group leader exits

group leader death

• group leader becomes controlling process of its terminal

• responsible for managing terminal for entire group

• group leader dies

o controlling terminal is disassociated from the group (( t_pgrp == 0

o all other group processes

▪ sent SIGHUP signal

▪ p_prgp == 0 ( do not belong to process group ( orphaned

implementation

• proc structure

o p_prgp field – contains the process group ID

• u area

o u_ttyp field – contains the pointer to tty structure of controlling terminal

▪ t_prgp field in the tty structure contains

the controlling process group of the terminal

o u_ttyd field – contains the device number of controlling terminal

u area tty structure of controlling terminal

limitations

• process group cannot close its controlling terminal and allocate another

• login session cannot be preserved after disconnecting from its controlling terminal

• no consistent method of handling “loss of carrier” by the controlling terminal; it is implementation dependent

• kernel cannot synchronize access to terminal by different processes in the group

• foreground/background processes read/write terminal in an unregulated manner

• process group leader terminates (

kernel sends SIGHUP signal to all processes in the group

o processes that ignore SIGHUP signal can continue to access the controlling terminal even after it is reassigned to another group

o possible security breaches, unsolicited data

• process other than login process invokes setpgrp

o process will be disconnected from controlling terminal

o process can continue to access the terminal via existing file descriptors

o process will not

▪ be controlled by the terminal

▪ receive SIGHUP signals

• no job control facilities

cannot move processes between foreground and background

• programs which open devices other than its controlling terminal have no way of

receiving carrier loss notification from those devices, i.e.,

terminal emulators

4.3BSD Groups & Terminals

process groups

• process group represents a job (task) within a login session

• job is a set of related processes that are controlled as a single unit with regard to terminal access

• process inherits group ID from parent

• setpgrp() – process can change

o its own group ID

o group ID of any other process that it owns

o superuser can change group ID of any process

• setpgrp() – arguments

o PID of target process

o new group ID

• process may relinquish leadership of group

• process may join any desired group

• process groups may have no leaders

jobs

• job control shells typically create new a process group for each command line

• a job usually consists of a

o a single process

o a set of descendent processes

o a set of unrelated processes connected by pipes

o a set of unconnected processes, e.g., combine unrelated processes into a single control group by issuing multiple shell commands on the same line, separated by semicolons and placed within parentheses, i.e.,

$ (cc junk.c; cp f1 f2; echo done>newfile)

login sessions

• single login session may generate several process groups that are

o all active at same time

o all sharing the same controlling terminal

o controlling terminal tty structure

t_pgrp field contains foreground job’s process group

controlling terminals

• process with group ID == zero

opens a terminal which is currently

o a controlling terminal for another group

▪ terminal becomes controlling terminal for that process

▪ process joins the terminals current controlling group

▪ process p_pgrp field is set to the terminal t_pgrp field value

o not a controlling terminal for another group

▪ process is made group leader

▪ process p_pgrp field & terminal t_pgrp field are set to the PID

▪ terminal becomes controlling terminal for that process

• direct descendents of init initially have a group ID == zero,

hence, all login shell processes have a group ID == zero

• only a superuser can reset a process’s group ID to zero

terminal access

• foreground processes,

i.e., the terminals controlling group,

have unobstructed access to the terminal

• background process

o attempt to read from the terminal

▪ driver sends SIGTTIN signal to all processes in group

▪ SIGTTIN suspends receiving process by default

o writes by a background process are permitted by default

o terminal option

▪ LTOSTOP bit manipulated by the TIOCLSET ioctl() function

▪ causes SIGTTOU signal to be sent to background process that tries to write to terminal

o jobs stopped by SIGTTIN or SIGTOU can be resumed by sending SIGCONT signal

controlling group

• process with terminal read access can use the TIOCSPGRP ioctl() function call to change terminal’s controlling group (t_prgp) to an arbitrary value

• shell uses ioctl() function call to move jobs to foreground/background

• user resumes suspended process group and moves it to the foreground by making it the controlling group and sending it a SIGCONT signal

• csh/ksh shells – provide fg/bg commands

closing terminal

• no process has terminal open

o terminal is disassociated from the group

o terminal’s t_pgrp field is set to zero

• last descriptor to terminal is closed

o terminal driver’s close routine is called

▪ terminal is disassociated from the group

▪ terminal’s t_pgrp field is set to zero

reinitializing the terminal line

• handling processes that continue after the login session terminates

• vhangup() system call

o used by init to terminate login session and initiate another login session

o traverses the open file table

▪ finds each entry that resolves to this terminal

▪ makes it unusable by deleting the open mode in the file table entry

o in implementations using the vnode interface

▪ change the vnodeops pointer to point to a set of functions that return an error

o calls the terminal close() routine

o sends SIGHUP signal to the terminal’s controlling group

drawbacks

• no clear representation of a login session

• no single process is responsible for controlling the terminal

• loss of carrier sends SIGHUP signal to it’s current controlling group which could be ignoring this signal

• process can change terminal’s controlling group to any value, even a nonexistent one

• programming interface is incompatible with System V

SVR4 Sessions Architecture

• process group – identifies a single job

• session object -- represents the login session

• allow login session to attach and detach several

controlling terminals during its lifetime

• allow terminal access based solely on file access permissions

• session leader is

o process that creates login session

o responsible for maintaining the session’s integrity and security

sessions & process groups

• each process belongs to both a

o session and

o process group

• each controlling terminal is associated with a

o session and

o foreground process group, i.e., the terminals controlling group

• session leader responsible for

o maintaining login session & insulating it from other sessions

o allocating/deallocating the controlling terminal

• process calling setsid()

o sets both session ID and group ID to the PID value

o makes caller both session leader and group leader; creates new session

o if process is already group leader

it cannot become session leader, setsid() fails,

does not creates a new session

• process groups

o have characteristics of 4.3BSD groups

o represent jobs within a login session

• single login session several process groups active simultaneously

• foreground group – unlimited access to terminal – terminal controlling group

• background processes that attempt to access the controlling terminal

are sent SIGTTIN or SIGTTOU signals

• process

o inherits its process group from its parent

o may change process groups by calling setpgid() or setpgrp()

o setpgrp() is identical to SVR3 version—sets caller’s group equal to its PID – making it a group leader

• setpgid(pid, pgid)

o similar to 4.3BSD setpgid() with restrictions on the operations

o pid of process group ( value specified by pgid

o pgid == 0 ( process group is set to same value as pid

making process a group leader

o pid == 0 ( call acts on calling process itself

o target process must be either the caller or a

child of caller that has not yet called exec()

o caller and target process must both belong to same session

o pgid != target pid ==> pgid must be equal to

another existing group ID within the same session

• process

o may move from one group to another within a session

o may leave session by calling setsid() to start a new session

with the process as sole member

o that is a group leader must relinquish leadership of its current group

in order to move to another group

o cannot start a new session as long as its PID is the group ID of any other process, i.e., the group whose leadership the process relinquished is not empty

• terminal’s foreground (controlling) group

o may only be changed by the process in the session that controls the terminal

o can only be changed to another valid group in the same session

data structures

session leader another proc session leader of foreground group

• gbyuo

• bnjip

o pgid != target pid ==> pgid must be equal to

o gyu9g80

-----------------------

SIGKILL & SIGSTOP signals cannot be ignored, blocked, nor handled by a signal handler function

actions can only be taken by the receiving process;

process can only take action when it is running;

if the process has low priority, is swapped out, suspended, or blocked there can be a considerable delay before action is taken

Job Control Shells -- csh, ksh

use signals to manipulate foreground & background processes

user types ^C at terminal

• terminal driver sends SIGINT signal to foreground process of terminal;

• when process is scheduled to run, after the context switch, but before returning to user mode, issig() will detect the signal;

• if foreground process is the currently running process at the time of the interrupt, the handller will interrupt the foreground process & post the signal to it; upon returning from the interrupt, the foreground process will detect the signal

exception occurs in current process

• kernel trap handler send appropriate signal to current process;

• before returning to user mode, trap handler calls issig()

if signal is generated for process in an uninterruptible sleep, the signal will be marked pending; process will not notice signal after waking up until it is about to return to user mode or block on an interruptible event;

if process is about to block on interruptible event, it will check for signals just before blocking; if signal is found, it handles the signal and aborts the system call; if signal is generated after the process has blocked, the kernel will wake the process; when process wakes up and runs – either because the event it was waiting for has occurred or because its sleep was interrupted by a signal -- it will call issig()

if kernel has to post a signal to a process in an interruptable sleep, it cannot know if the process will ignore the signal;

spurious wakeups ( unnecessary context switches

SVR2 lacks

facility to block signals

support for job control; where groups of processes can be suspended and resumed in order to control terminal access

handler always runs with the current signal blocked,

second instance of signal will not be delivered until handler completes;

signal handlers are critical code sections;

when the handler returns, the blocked signals mask is restored to its prior value

sigstack() system call specifies separate stack for the handler;

user must manage the stack size

slow system calls aborted by signals are automatically restarted;

• read & write system calls to character devices

• network connections

• pipes

• wait()

• waitpid()

• ioctl()

• etc

deficiency: lack of compatibility with SVRx

SA_NODEFER flag is specified ( current signal not added to mask

SA_RESETHAND flag is specified ( action in u_signal[] array reset to SIG_DFL

u_ttyp

u_ttyd device number

t_prgp terminal controlling group

struct tty

t_pgrp

struct session

tty device number

vnode ptr

vnode of stream for tty

proc

p_sessp

proc

p_sessp

proc

p_sessp

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download