Signals and Message Queues

April 8, 2013 Inter- Communication • Why IPC? Allows for processes to work together, but remain otherwise isolated.

• Segment-based IPC – Ex: memory-mapped files, shared memory

• Stream-based IPC – Ex: pipes, fifos, network sockets

• Message-based IPC – Ex: signals, message queues, message passing Signals are “events” • Signals communicate asynchronous events Signal Event Default Action SIGINT “Interactive Attention” (usually Ctrl+C) Process termination SIGSEGV Non-mapped Memory Access (seg. fault) Process termination SIGTERM Request for process termination (eg: Process termination system is being shut down) SIGCHLD Child process terminated, stopped, or Nothing (ignored) continued SIGSTOP* Stops process execution Stop SIGKILL* Kills process Process termination SIGALRM System alarm clock expired Process termination SIGUSR1 User-defined event Process termination SIGUSR2 User-defined event Process termination

Inter-Process Communication • On Friday, we replaced the default handler with a custom-defined signal handler.

• Problem: What if we get a signal while we are in our signal handler? Signal Mask • A signal mask is a mask that will preserve the existence of a signal, but block it from being handled until the mask is removed.

INT QUIT SEGV TERM USR1 USR2 Signal Bitmap: 0 0 0 0 1 0 ... Signal Mask: 1 0 1 0 1 0 ...

Every process has its own unique signal bitmap and mask! Modifying the Signal Mask

Examine and change blocked signals: sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

Manipulate the sigset_t set: sigemptyset(sigset_t *set); sigfullset (sigset_t *set); sigaddset (sigset_t *set, int sig); sigdelset (sigset_t *set, int sig); sigismember(sigset_t *set, int sig);

Signal Handlers and Signal Masks • As part of installing a custom signal handler, we also specify a custom signal mask to be applied while we handle the signal. How? • Using the easy way to handle a signal, using signal(): – The signal mask applied to our signal handler blocks only the signal that was delivered.

• The proper way: int sigaction( int signum, struct sigaction *act, struct sigaction *oldact);

struct sigaction { void (*sa_handler)(int); sigset_t sa_mask; ... };

A Signal’s Lifecycle Code Example void handler(int sig) { printf(“In signal handler!”); while (1) { } } int main() { signal(SIGINT, handler); while (1) { } return 0; } Some Other Common Uses of Signals

: int alarm(int seconds) – Set an alarm clock for the delivery of a signal. – Usage: Log system state every X seconds to a log file.

• Debugging: Many programs use a signal to print debugging information. – In Java: Pressing Ctrl+\ (SIGQUIT) on a Java process will print out the current state of every .

• Interrupting blocking calls: Many C system calls will return if a signal is delivered to your process. – Eg: write(), sleep(), etc. Common Interview Question

• If they only IPC mechanism you have are signals, how can I create a program to send a long message (eg: any string) from a server to a client? Message Queues • The POSIX solution to passing a message: message queues. – Multiple processes register to the same message queue using mq_open().

– A process sends a message with mq_send(). • Sends a string up to a system-defined length (~8 KB)

– A process can receive a message by: • Calling mq_receive(), a blocking call.  • Calling mq_notify(), setting up for a signal to be sent when a message is received. Message Queues • Why are message queues rarely used?