Skip to main content

Multi-language CLI tool for detecting concurrency and thread safety issues

Project description

Thread Safety Analyzer

A multi-language static analysis tool for detecting concurrency and thread safety issues. Use it locally as a linter, in CI pipelines, or to generate context for LLM-assisted PR reviews.

Installation

pip install thread-safety

Or install from source:

git clone https://github.com/steph-dove/thread-safe-check.git
cd thread-safe-check
pip install -e .

Use Cases

Local Development (Linter)

Run as a linter during development to catch concurrency issues early:

# Analyze your project
thread-safety analyze ./src

# Check only files you've changed
thread-safety analyze . --git-diff

# Focus on critical issues
thread-safety analyze ./src --min-severity high

CI/CD Integration

Add to your CI pipeline to catch thread safety issues before merge.

GitHub Actions:

- name: Thread Safety Check
  run: |
    pip install thread-safety
    thread-safety analyze ./src --output json -f thread-safety-report.json

- name: Upload Report
  uses: actions/upload-artifact@v3
  with:
    name: thread-safety-report
    path: thread-safety-report.json

GitLab CI:

thread-safety:
  script:
    - pip install thread-safety
    - thread-safety analyze ./src --min-severity medium
  allow_failure: true  # Start as warning-only

Pre-commit Hook:

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: thread-safety
        name: Thread Safety Check
        entry: thread-safety analyze
        language: system
        files: \.(py|js|ts|go|rs)$
        pass_filenames: false

LLM PR Review Context

Generate rich context for AI-assisted code review:

# Generate LLM-optimized output
thread-safety analyze ./src --output llm

# Analyze only changed files for PR review
thread-safety analyze . --git-diff --output llm

The LLM output format includes:

  • Code snippets with context
  • Detailed explanations of why each issue matters
  • Suggested fixes with before/after examples
  • Severity and category information

Quick Start

# Analyze a directory
thread-safety analyze ./src

# Output formats
thread-safety analyze ./src --output text      # Human-readable (default)
thread-safety analyze ./src --output json      # For CI/tooling
thread-safety analyze ./src --output markdown  # For documentation
thread-safety analyze ./src --output llm       # For AI review

# Filter by severity (info, low, medium, high, critical)
thread-safety analyze ./src --min-severity high

# Run specific rules only
thread-safety analyze ./src --rule TS001 --rule TS010

# Analyze only git-changed files
thread-safety analyze . --git-diff

# Save report to file
thread-safety analyze ./src --output json -f report.json

# List all available rules
thread-safety rules

# Generate config file
thread-safety init

Detection Rules

Shared Mutable State

  • TS001: Global variable mutation in threaded context
  • TS002: Class attribute mutation across threads
  • TS003: Closure capturing mutable variable
  • TS004: Module-level mutable default argument

Race Conditions

  • TS010: Unprotected shared variable access
  • TS011: Check-then-act (TOCTOU)
  • TS012: Compound operation without lock
  • TS013: Collection modification during iteration

Lock Issues

  • TS020: Potential deadlock (inconsistent lock ordering)
  • TS021: Lock acquired but never released
  • TS022: Double lock acquisition (non-reentrant)
  • TS023: Lock held during blocking I/O

Async Patterns

  • TS030: Blocking call in async function
  • TS031: Missing await on coroutine
  • TS032: Using threading.Lock in async code
  • TS033: Shared mutable state in coroutine
  • TS034: Sync primitive in async context

Supported Languages

Language Status Rules Notes
Python ✅ Stable 17 Full coverage
JavaScript/TypeScript ✅ Stable 8 Async/Promise patterns
Go ✅ Stable 5 Goroutines, sync.Mutex
Rust ✅ Stable 8 Async, std::sync
Java Planned - -

Language Support Matrix

Rule Python JS/TS Go Rust
TS001 Global Mutation - - -
TS002 Class Attribute - - -
TS003 Closure Capture
TS004 Mutable Default - - -
TS010 Unprotected Access - - -
TS011 Check-Then-Act
TS012 Compound Operation - - -
TS013 Collection Iteration
TS020 Deadlock -
TS021 Lock Not Released - - -
TS022 Double Lock - - -
TS023 Lock Blocking I/O -
TS030 Blocking in Async -
TS031 Missing Await -
TS032 Threading Lock in Async - - -
TS033 Shared State in Coroutine -
TS034 Sync Primitive in Async - - -

Configuration

Create a thread-safety.toml file in your project root:

[thread-safety]
include = ["src", "lib"]
exclude = ["**/node_modules/**", "**/.venv/**", "**/test/**"]
min_severity = "medium"

[thread-safety.rules]
# Enable only specific rules
enable = ["TS001", "TS010", "TS020"]

# Or disable specific rules
disable = ["TS004"]

Output Formats

Text (default)

Human-readable output for terminal with colors and code snippets.

JSON

Structured output for CI/CD integration and tooling:

thread-safety analyze ./src --output json -f report.json

Markdown

Documentation-friendly format for reports:

thread-safety analyze ./src --output markdown -f report.md

LLM

Optimized for AI-assisted code review with rich context:

thread-safety analyze ./src --output llm

Example Output

Found 2 issue(s):

■ TS030  src/api/handler.py:45:4
  Blocking call 'requests.get' in async function 'fetch_data'

       43 | async def fetch_data(url: str):
       44 |     # This blocks the event loop!
    >  45 |     response = requests.get(url)
       46 |     return response.json()

  Suggestion: Replace with async alternative: aiohttp or httpx

■ TS013  src/cache.py:23:8
  Collection 'items' modified with 'pop' during iteration

       21 |     for key in cache.items:
       22 |         if is_expired(key):
    >  23 |             cache.items.pop(key)
       24 |

  Suggestion: Collect keys to remove first, then remove outside the loop

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
ruff check src tests

# Type checking
mypy src

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thread_safe_check-0.4.0.tar.gz (60.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thread_safe_check-0.4.0-py3-none-any.whl (89.5 kB view details)

Uploaded Python 3

File details

Details for the file thread_safe_check-0.4.0.tar.gz.

File metadata

  • Download URL: thread_safe_check-0.4.0.tar.gz
  • Upload date:
  • Size: 60.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for thread_safe_check-0.4.0.tar.gz
Algorithm Hash digest
SHA256 b5d8b92246cad5c77d7fd46e293deb826e8adc8772439d8f926e2b541b4926f7
MD5 fb4e25e59d702ed27f961e3bac484317
BLAKE2b-256 8477607c1cdffb2eb8fff3fdedf81b8cd179c5abf81b6d041eb01132ac044764

See more details on using hashes here.

File details

Details for the file thread_safe_check-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for thread_safe_check-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8e761a4a4175519987265e1bfe75f838b124c0b2451c86a6c35c3b3b9bb922f2
MD5 d31bf578dc7e0d436e2aa0ce96496087
BLAKE2b-256 3553881ea353a19843d2c669e3e67550957183d68c5c598d7e0b22c4bca6432b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page