Skip to content

Windows crash: AttributeError signal.SIGALRM not available (POSIX-only) in _scan_file #17

@A3E-ECOSYSTEM

Description

@A3E-ECOSYSTEM

Summary

ails check crashes on Windows before reporting any findings. The deterministic checks phase hits a hard AttributeError because signal.SIGALRM / ITIMER_REAL is POSIX-only and does not exist on Windows.

Environment

  • OS: Windows 11 Pro 10.0.26200
  • Command: npx @reporails/cli check (unauthenticated)
  • Shell: bash (Git Bash / Claude Code terminal)

Full traceback

AttributeError: module 'signal' has no attribute 'SIGALRM'
  File: reporails_cli/core/regex/runner.py, line 367, in _scan_file
    prev = signal.signal(signal.SIGALRM, _alarm_handler)

The crash occurs in _scan_file when registering the per-file timeout handler. On Windows, signal.SIGALRM is not defined — the module exists but the attribute does not. The entire deterministic checks phase is skipped and no findings are returned.

Suggested fix

Replace the SIGALRM-based timeout with a threading.Timer fallback on Windows:

import signal, sys, threading

def _scan_file_with_timeout(fn, timeout_seconds):
    if sys.platform != 'win32':
        # POSIX path — existing SIGALRM logic unchanged
        prev = signal.signal(signal.SIGALRM, _alarm_handler)
        signal.setitimer(signal.ITIMER_REAL, timeout_seconds)
        try:
            return fn()
        finally:
            signal.setitimer(signal.ITIMER_REAL, 0)
            signal.signal(signal.SIGALRM, prev)
    else:
        # Windows path — threading.Timer in daemon thread
        result, exc = [None], [None]
        def target():
            try: result[0] = fn()
            except Exception as e: exc[0] = e
        t = threading.Thread(target=target, daemon=True)
        t.start()
        t.join(timeout=timeout_seconds)
        if t.is_alive():
            raise TimeoutError(f"_scan_file timed out after {timeout_seconds}s")
        if exc[0]: raise exc[0]
        return result[0]

Alternatively, a one-line minimal fix: wrap the signal.signal / signal.setitimer calls in if hasattr(signal, 'SIGALRM'): and skip the timeout on Windows.

Context

Found while running ails check against a 21-rule CLAUDE.md (~3 KB, governance + operational rules). Reported from the DEV.to corpus analysis thread — happy to test a 0.5.5 pre-release build on Windows if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions