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_safety-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_safety-0.4.0-py3-none-any.whl (89.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: thread_safety-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_safety-0.4.0.tar.gz
Algorithm Hash digest
SHA256 778244f825472f7e16f87782f9301a6185691d2f59399700118c2eed6a135bbd
MD5 e970df66cc60bc804e727baddd5a768d
BLAKE2b-256 a79e9a28e140b244a43a50c5fc5e6c0db53f766d2a144398bde221d707084de8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: thread_safety-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 89.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for thread_safety-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 40a9556641227c1c5895eb121aab65d224f0938e42a8363121171050be08142d
MD5 4a9bb877d23c2f7cd72069b2bb88417b
BLAKE2b-256 e66b2d8a2a9dcf92fa62db019aac7c4e7bf0d94c25b365b0136d61fc6355af6a

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