Pipes and Signals
Challenge Gallery
Quick Reference
Pipe pattern:
int fd[2];
pipe(fd); // fd[0] = read end, fd[1] = write end
if (fork() == 0) { // Child (writer)
close(fd[0]); // Close unused read end
write(fd[1], data, len);
close(fd[1]);
exit(0);
} else { // Parent (reader)
close(fd[1]); // Close unused write end
read(fd[0], buf, sizeof(buf));
close(fd[0]);
wait(NULL);
}
Common signals:
| Signal | Number | Default | Catchable? |
|---|---|---|---|
| SIGINT | 2 | Terminate | Yes |
| SIGTERM | 15 | Terminate | Yes |
| SIGKILL | 9 | Terminate | No |
| SIGSEGV | 11 | Core dump | Yes |
| SIGPIPE | 13 | Terminate | Yes |
Common Pitfalls
- Pipe before fork – The pipe must be created before fork(). Otherwise parent and child have separate pipes.
- Close unused ends – Failing to close causes deadlocks (read blocks forever waiting for EOF).
- Zombie processes – Always wait() for children. Use WNOHANG for non-blocking checks.
- Signal handler safety – Only call async-signal-safe functions (write, _exit) inside handlers. printf is NOT safe.