Skip to content

python.race_condition

Correctness High

Detects potential race conditions from concurrent access to shared state without proper synchronization.

Race conditions cause:

  • Intermittent bugs — Problems that appear and disappear randomly
  • Data corruption — Concurrent writes can corrupt shared state
  • Hard to reproduce — Issues only manifest under specific timing
  • Production-only failures — Tests often pass due to lower load
# ❌ Before (race condition risk)
counter = 0
async def increment():
global counter
temp = counter
await asyncio.sleep(0) # Yield control
counter = temp + 1 # Another task may have modified counter
# ✅ After (with synchronization)
import asyncio
counter = 0
lock = asyncio.Lock()
async def increment():
global counter
async with lock:
counter += 1
  • Global variables modified in async functions without locks
  • Shared state accessed across coroutines without synchronization
  • Check-then-act patterns in concurrent code
  • Non-atomic read-modify-write operations

Unfault generates patches that add appropriate synchronization:

import asyncio
from threading import Lock
# For async code
async_lock = asyncio.Lock()
async def safe_update():
async with async_lock:
# Protected code here
pass
# For threaded code
thread_lock = Lock()
def safe_update_threaded():
with thread_lock:
# Protected code here
pass
# Use thread-safe data structures
from collections import deque
from queue import Queue
# Or use atomic operations
import threading
counter = threading.Counter() # Python 3.12+
# Or use contextvars for request-scoped state
import contextvars
request_state = contextvars.ContextVar('request_state')