Project 3: The Hang - Attaching to a Running Process
Attach LLDB to a live process, inspect threads, and detach safely.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Intermediate |
| Time Estimate | 2-3 hours |
| Language | C (LLDB commands) |
| Prerequisites | Projects 1-2, process basics |
| Key Topics | Attach/detach, thread backtraces |
1. Learning Objectives
By completing this project, you will:
- Attach LLDB to a running process by PID.
- Inspect thread states and backtraces.
- Identify where a program is blocked.
- Detach without killing the process.
2. Theoretical Foundation
2.1 Core Concepts
- Attach: Connect LLDB to a running process.
- SIGSTOP: A signal used to pause a process.
- Thread backtrace: The stack for each thread.
2.2 Why This Matters
In production, you cannot restart or recompile a hung service. Attach-and-inspect is your primary tool.
2.3 Common Misconceptions
- “Attach kills the process.” (It only pauses it temporarily.)
- “Only one thread matters.” (Hangs often involve multiple threads.)
3. Project Specification
3.1 What You Will Build
A small program that loops forever. You will attach LLDB to it from a second terminal and inspect its state.
3.2 Functional Requirements
- Attach by PID and verify the process stops.
- Print thread backtraces and identify the blocked thread.
- Modify a variable at runtime.
- Detach cleanly.
3.3 Non-Functional Requirements
- Safety: Detach without killing the process.
- Clarity: Notes clearly identify where the program is blocked.
3.4 Example Usage / Output
(lldb) process attach --pid 12345
(lldb) thread backtrace all
(lldb) detach
3.5 Real World Outcome
$ clang -g -O0 -o hang hang.c
$ ./hang
$ pgrep hang
12345
$ lldb
(lldb) process attach --pid 12345
Process 12345 stopped
* thread #1, stop reason = signal SIGSTOP
frame #0: 0x00007fff2031d7d8 libsystem_c.dylib`nanosleep
(lldb) thread backtrace all
(lldb) frame select 1
(lldb) frame variable counter
(int) counter = 10
(lldb) expr counter = 100
(int) $0 = 100
(lldb) detach
Process 12345 detached
4. Solution Architecture
4.1 High-Level Design
Live Process -> Attach -> Inspect Threads -> Modify State -> Detach
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Running process | Provide live state | Use deterministic loop |
| LLDB attach | Pause and inspect | Attach by PID |
| Thread analysis | Find hang point | thread backtrace all |
5. Implementation Guide
5.1 Development Environment Setup
clang -g -O0 -o hang hang.c
./hang
5.2 Project Structure
project-root/
|-- hang.c
`-- notes.md
5.3 The Core Question You’re Answering
“How do I pause a live process, inspect its threads, and leave it running safely?”
5.4 Concepts You Must Understand First
- Process and thread states
- Book: Operating Systems: Three Easy Pieces - Ch. 4-5, 26
- Attach/detach workflow
- Book: The Art of Debugging with GDB, DDD, and Eclipse - Ch. 2-3
- Stack frames
- Book: Computer Systems: A Programmer’s Perspective - Ch. 3
5.5 Questions to Guide Your Design
- How do you identify which thread is blocked?
- How do you tell if you are inside your code vs a library call?
- How do you modify a variable safely at runtime?
5.6 Thinking Exercise
List three reasons a program might hang and describe the backtrace you would expect for each.
5.7 The Interview Questions They’ll Ask
- What is the difference between attaching and launching?
- How do you detect a deadlock with a debugger?
- Why is detaching important for production systems?
- What does SIGSTOP mean in this context?
5.8 Hints in Layers
Hint 1: List threads first
(lldb) thread list
Hint 2: Dump all backtraces
(lldb) thread backtrace all
Hint 3: Change a variable live
(lldb) expr counter = 100
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Processes | Operating Systems: Three Easy Pieces | Ch. 4-5 |
| Threads | Operating Systems: Three Easy Pieces | Ch. 26 |
| Debugging workflow | The Art of Debugging with GDB, DDD, and Eclipse | Ch. 2-3 |
5.10 Implementation Phases
Phase 1: Setup (30 min)
- Build and run the hang program.
Phase 2: Attach + Inspect (60 min)
- Attach to the PID and inspect thread backtraces.
Phase 3: Modify + Detach (30 min)
- Change a variable, then detach cleanly.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| Attach method | PID vs name | PID | Deterministic |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Attach tests | Verify attach works | SIGSTOP in LLDB |
| Thread inspection | Ensure visibility | Backtraces available |
6.2 Critical Test Cases
- LLDB attaches and stops process.
- Backtrace shows the loop in your code.
7. Common Pitfalls & Debugging
| Pitfall | Symptom | Solution |
|---|---|---|
| Permission denied | Attach fails | Use same user or sudo |
| No symbols | ?? frames |
Rebuild with -g |
8. Extensions & Challenges
- Add a mutex and create a real deadlock to inspect.
- Attach to a long-running system service (non-destructive).
9. Real-World Connections
- Incident response often starts with attaching to a hung service.
- Thread backtraces are the fastest way to find lock contention.
10. Resources
- LLDB Command Reference: https://lldb.llvm.org/use/commandref.html
- LLDB Tutorial: https://lldb.llvm.org/use/tutorial.html
11. Self-Assessment Checklist
- I can attach and detach without killing a process.
- I can identify where a program is blocked.
- I can change a variable at runtime.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Attach to a running process.
- Produce a thread backtrace.
Full Completion:
- Modify a variable and detach safely.
Excellence (Going Above & Beyond):
- Debug a real deadlock you created.
This guide was generated from LEARN_LLDB_DEEP_DIVE.md. For the full learning path, see the parent directory README.