Staff / expert · Concurrency

Deadlock and lock ordering

How do you debug a service that is alive but no longer processes requests?

Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.

Reveal a strong answer
  1. Capture goroutine stacks and look for common waits: a mutex held across I/O, a full channel with no consumer, a WaitGroup whose owner waits before starting the receiver, or a cyclic lock acquisition.

  2. Use a consistent global lock order when two locks are unavoidable. Shrink critical sections and avoid callbacks under locks because callbacks can reenter code or acquire locks in unknown order.

  3. A partial deadlock may not trigger the runtime all-goroutines-asleep panic while timers or background goroutines continue. Expose queue progress and dependency health, not just process liveness.

Common trap

A running health endpoint does not prove the worker pipeline is making progress.

Try it

A producer must finish before the main goroutine begins receiving an unbuffered results channel. Explain the cycle.

Worked solution

The producer cannot finish until a receiver accepts its send, while the receiver waits for producer completion. Receive concurrently, or arrange a coordinator to close after producers finish while the collector drains.

Change the constraint

What would a block profile add beyond one snapshot of goroutine stacks?

How did you do?

Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.

Not marked. Progress stays on this browser, separate from course completion.

Primary references

Checked 2026-10-20. Use documentation for your pinned runtime, driver and tool version.