concurrency and caching of state

Bugs of Shared State

Bugs caused by concurrency, caching, and the distribution of state across multiple independent actors or processes.

State changes may not be instantaneous, may not be everywhere, and may not be complete.

01the defects

The defects in detail

timing, not logic, picks the answerRace ConditionsWhen two actors touch one value at once, the interleaving decides the (wrong) result.Read the defect one actor's data, served to anotherCross-Boundary State ExposurePer-actor state parked in a shared singleton, global, or pool bleeds across the boundary that was meant to keep actors apart.Read the defect the tragedy of the commonsResource ContentionIndependent actors each act in self-interest and exhaust a shared, finite resource.Read the defect recursion with no floorStack Overflow BugsA call stack that never unwinds, or a heap that never stops growing, runs out of room.Read the defect messages sent, never deliveredAsync IO MisuseFire-and-forget work drops results and failures no one notices are gone.Read the defect dangling, double-freed, used-after-freePointer MismanagementA pointer outlives what it points to, and the bytes start to lie.Read the defect stale data, served with confidenceCache InvalidationA write that does not invalidate is a bug waiting for the next read.Read the defect locks held, ordered, or forgottenThreading & MutexesThe lock that protects you from a race is the lock that deadlocks you.Read the defect the world between processes is unreliableFile & Network AccessDisk and network calls fail partway, arrive twice, or never arrive at all.Read the defect opened, never closedResource Leaks & Improper ShutdownA handle held past its lifetime — file, socket, connection, lock — is shared state nobody released; leaks accumulate until the system starves.Read the defect
02the smell

In practice

Every defect on this page comes from state shared across actors that don't move in lockstep. It shows up as data that's stale, out of order, or 'works on my machine.' The tools that make it easy are threads and mutexes, caches, pass-by-reference, and async code that drops the ball.

How it shows up

  • Data is inaccessible or out of order
  • Resources are slow or unavailable
  • Information is wrong or outdated
  • Communications are being dropped
  • “Works on my machine”

Tools that hurt

threading / mutexeshigh availabilityreplication and shardingoperations sloppinesspass-by-referenceasync mismanagement
03computer / human

Every shared-state bug has a human name

Every shared-state problem has a human name. Computers just hit them faster.
Computer
Human
Why it's the same problem
Cache Invalidation
Product Recalls
A product is supplied from a distribution point; changing it means changing every distribution. Invalidation is business logic, a work order that takes a process and happens now.
Cross-Boundary State Exposure
Crossed Phone Lines
On an old party line, one household could lift the receiver and hear another's call. Shared state reused across actors leaks one person's data to the next.
Resource Contention
Tragedy of the Commons
Independent actors each act in their own best interest and deplete a shared resource through uncoordinated allocation.
Async Misuse
Undeliverable Mail
Messages in transit occupy space, and not every message sent over the network gets through. No message may be silently dropped.
04stalls

Two ways concurrency achieves nothing

Two ways concurrency stalls. Both achieve nothing.
Failure
Like
What happens
Deadlock
an impasse
Multiple actors wait on one another, each paused until an impossible condition is met. NOTHING IS HAPPENING. NOTHING IS ACHIEVED.
Livelock
two people dodging in a hallway
Actors execute too early and keep reacting to each other; success is impossible unless someone waits. SO MUCH IS HAPPENING. NOTHING IS ACHIEVED.
05execution model

How far you are from the metal

How far you are from the metal decides what a shared-state bug costs you.
Model
Languages
How failure behaves
Interpreted
Python, JavaScript, Ruby
Runs inside an interpreter process. Runtime exceptions; the interpreter does its best to recover.
Compiled (VM)
Java, C#
Bytecode on a sandboxed virtual machine. Exceptions are handled by the VM; recovery is possible.
Executed (native)
C, Rust, Assembly
Architecture-specific machine code. No exceptions, only segfaults. Memory safety is the whole game.
06antidotes

Philosophies & antidotes

This family maps to the CWE pillar: CWE-662 — Improper Synchronization