Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

Unreleased
----------

- Fix macOS multiprocessing compatibility with timeout decorators

5.10.12
-------

Expand Down
34 changes: 32 additions & 2 deletions checkdmarc/smtp.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,36 @@
STARTTLS_CACHE = ExpiringDict(max_len=200000, max_age_seconds=1800)


def _get_timeout_method():
"""
Determine the best timeout method based on platform and environment.

Returns:
bool: True to use signals, False to use multiprocessing
"""
# On macOS, use signals to avoid multiprocessing spawn issues
if platform.system() == "Darwin":
return True

# On Windows, signals are not available, so use multiprocessing
if platform.system() == "Windows":
return False

# On Linux and other Unix-like systems, prefer signals for better performance
# unless we detect we're in a multithreaded environment
try:
# Check if we're in a multithreaded environment by looking for threading
import threading
if threading.active_count() > 1:
# Multiple threads detected, use multiprocessing to avoid signal conflicts
return False
except ImportError:
pass

# Default to signals for better performance on Unix-like systems
return True


class SMTPError(Exception):
"""Raised when SMTP error occurs"""

Expand All @@ -51,7 +81,7 @@ class SMTPError(Exception):
5,
timeout_exception=SMTPError,
exception_message="Connection timed out",
use_signals=False,
use_signals=_get_timeout_method(),
)
def test_tls(
hostname: str, *, ssl_context: ssl.SSLContext = None, cache: ExpiringDict = None
Expand Down Expand Up @@ -168,7 +198,7 @@ def test_tls(
5,
timeout_exception=SMTPError,
exception_message="Connection timed out",
use_signals=False,
use_signals=_get_timeout_method(),
)
def test_starttls(
hostname: str, *, ssl_context: ssl.SSLContext = None, cache: ExpiringDict = None
Expand Down
Loading