# Troubleshooting Connection Timeouts and Implementing Retry Logic in Patator

> Troubleshoot Patator connection timeouts with its dual-layer strategy and implement robust retry logic featuring linear back-off and custom triggers for smoother operations.

- Repository: [lanjelot/patator](https://github.com/lanjelot/patator)
- Tags: deep-dive
- Published: 2026-03-05

---

**Patator employs a dual-layer timeout strategy combining UNIX signal alarms with module-level socket timeouts, paired with a configurable retry loop that supports linear back-off and user-defined conditional triggers.**

When brute-forcing services across unreliable networks, handling intermittent failures is critical. The Patator framework implements robust **troubleshooting connection timeouts** and **implementing retry logic** mechanisms directly in its core controller located in [`src/patator/patator.py`](https://github.com/lanjelot/patator/blob/main/src/patator/patator.py). These features ensure that transient network issues do not terminate valid attack sequences while preventing infinite loops on permanently offline hosts.

## Global Timeout Configuration and Signal-Based Enforcement

Patator exposes a global `--timeout` parameter (defined at line 826) that controls how long the framework waits for a single payload attempt. Internally, the `Controller` class stores this value and activates a UNIX-specific alarm mechanism through the `enable_alarm` method found around line 647.

When a payload executes, the controller invokes `signal.alarm(self.timeout)` before calling the module's `execute` method. If the operation exceeds the specified duration, the `raise_timeout` handler (line 643) interrupts execution by raising a `TimeoutError`. This signal-based approach ensures that hanging connections cannot block the consumer thread indefinitely.

The alarm is automatically cleared in the exception handling block (lines 1406-1419), where the framework constructs a generic failure `Response` and optionally invokes the module's `reset` method to purge persistent connections.

## Module-Level Socket Timeouts

Beyond the controller-level alarm, Patator propagates the timeout value to underlying network libraries to ensure consistent behavior. Each module forwards the `timeout` argument to its specific implementation:

- **HTTP module**: Sets `pycurl.TIMEOUT` (line 3275)
- **SSH/FTP modules**: Pass timeout to `socket.create_connection()` or library constructors like `FTP(timeout=int(timeout))`

This dual enforcement ensures that even on platforms where signal alarms are unavailable, the underlying socket operations respect the user-defined limits.

## Configurable Retry Logic with Linear Back-Off

Patator implements **implementing retry logic** through a dedicated retry loop in the consumer thread (starting at line 1399). The `--max-retries` option (default 4, defined at line 827) controls how many additional attempts occur after an initial failure.

The retry mechanism operates as follows:

1. Initialize `try_count` at 0
2. Check condition: `if try_count <= self.max_retries or self.max_retries < 0:`
3. On failure, increment counter and sleep for `try_count * 0.1` seconds (lines 1424-1425)
4. If the module exposes a `reset` method, invoke it to close stale connections (lines 1421-1422)
5. Repeat until success or limit reached

Setting `--max-retries -1` enables unlimited retries, useful when probing intermittently available services.

```bash

# Basic usage with 10-second timeout and 3 retries

patator ssh_login host=10.0.0.1 user=FILE0 0=users.txt password=FILE1 \
    --timeout 10 --max-retries 3

```

## Dynamic Retry Actions for Conditional Logic

Users can define granular retry conditions using the `-x retry:` action syntax. When specified, Patator evaluates response conditions (status codes, error messages) and injects the `'retry'` action into the processing pipeline.

The `lookup_actions` function parses these rules, and the `report_progress` method handles them in the consume loop (around lines 1450-1454). When `'retry'` appears in the action set, the loop continues without marking the payload as completed, subject to the global retry limit.

```bash

# Retry only on 5xx HTTP errors, fail immediately on 4xx

patator http_login host=10.0.0.1 user=FILE0 0=users.txt \
    -x retry:code=5[0-9]{2} --max-retries 3 --timeout 10

# Retry specifically on connection timeout messages

patator ftp_login host=10.0.0.1 user=admin password=FILE0 \
    -x retry:mesg='timed out' --timeout 5 --max-retries 5

```

## Cross-Platform Timeout Behavior

On UNIX systems, both the signal alarm and module-level timeouts operate simultaneously, providing redundant protection. On Windows, the `enable_alarm` function becomes a no-op because Python's `signal` module lacks `SIGALRM` support. However, **troubleshooting connection timeouts** remains effective through module-level socket timeouts, ensuring consistent cross-platform behavior.

## Summary

- Patator uses UNIX `signal.alarm` in `enable_alarm` to enforce per-payload timeouts, falling back to socket timeouts on Windows.
- The `--timeout` parameter controls both the controller alarm and module-level network calls (e.g., `pycurl.TIMEOUT`).
- Retry logic supports configurable limits via `--max-retries` (including unlimited with `-1`) and linear back-off via `sleep(try_count * .1)`.
- Failed attempts automatically trigger module `reset` methods to clear persistent connections.
- Dynamic `-x retry:` actions allow conditional retries based on response codes or messages.

## Frequently Asked Questions

### How does Patator handle timeouts on Windows without SIGALRM support?

On Windows, Patator disables the signal alarm mechanism (`enable_alarm` becomes a no-op), but module-level socket timeouts remain fully functional. Each module passes the `--timeout` value directly to underlying libraries like `socket.create_connection()` or `pycurl`, ensuring connections still terminate after the specified duration.

### What is the maximum number of retries Patator allows?

Patator defaults to 4 retries per payload, but you can configure this via `--max-retries`. Setting the value to `-1` enables unlimited retries, causing the consumer loop to continue indefinitely until the payload succeeds or the process is manually terminated.

### Can I retry only on specific HTTP status codes while failing immediately on others?

Yes, use the conditional retry action syntax: `-x retry:code=5[0-9]{2}` retries only on 5xx server errors, while `-x retry:mesg='Connection refused'` retries on specific error messages. This integrates with the dynamic action system in `report_progress` (lines 1450-1454), allowing fine-grained control over which failures warrant retry attempts.

### Why does Patator implement a back-off sleep between retries?

The framework sleeps for `try_count * 0.1` seconds between attempts to prevent aggressive polling that could overwhelm unresponsive services or trigger rate limiting. This linear back-off gives temporary network issues time to resolve while keeping the brute-force process moving forward.