mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-03 16:22:49 +00:00
fix: handle missing signals on Windows (SIGHUP, SIGTSTP, SIGCONT)
This fixes GitHub issue #4062 where crewai crashes on Windows with 'module signal has no attribute SIGHUP' error. Changes: - Use getattr with fallback values for signals not available on Windows - Make telemetry signal registration conditional on signal availability - Add regression tests for Windows compatibility The fix maintains backward compatibility on Unix systems while allowing crewai to work on Windows where SIGHUP, SIGTSTP, and SIGCONT are not available. Co-Authored-By: João <joao@crewai.com>
This commit is contained in:
@@ -24,12 +24,25 @@ class TestSignalType:
|
||||
"""Tests for SignalType enum."""
|
||||
|
||||
def test_signal_type_values(self) -> None:
|
||||
"""Verify SignalType maps to correct signal numbers."""
|
||||
"""Verify SignalType maps to correct signal numbers when available."""
|
||||
assert SignalType.SIGTERM == signal.SIGTERM
|
||||
assert SignalType.SIGINT == signal.SIGINT
|
||||
assert SignalType.SIGHUP == signal.SIGHUP
|
||||
assert SignalType.SIGTSTP == signal.SIGTSTP
|
||||
assert SignalType.SIGCONT == signal.SIGCONT
|
||||
|
||||
# These signals are not available on Windows, so only check if present
|
||||
if hasattr(signal, "SIGHUP"):
|
||||
assert SignalType.SIGHUP == signal.SIGHUP
|
||||
if hasattr(signal, "SIGTSTP"):
|
||||
assert SignalType.SIGTSTP == signal.SIGTSTP
|
||||
if hasattr(signal, "SIGCONT"):
|
||||
assert SignalType.SIGCONT == signal.SIGCONT
|
||||
|
||||
def test_signal_type_enum_members_always_exist(self) -> None:
|
||||
"""Verify all SignalType enum members exist regardless of platform."""
|
||||
assert hasattr(SignalType, "SIGTERM")
|
||||
assert hasattr(SignalType, "SIGINT")
|
||||
assert hasattr(SignalType, "SIGHUP")
|
||||
assert hasattr(SignalType, "SIGTSTP")
|
||||
assert hasattr(SignalType, "SIGCONT")
|
||||
|
||||
|
||||
class TestSignalEvents:
|
||||
@@ -194,4 +207,71 @@ class TestSignalEventSerialization:
|
||||
restored = signal_event_adapter.validate_python(serialized)
|
||||
assert isinstance(restored, SigTermEvent)
|
||||
assert restored.reason == original.reason
|
||||
assert restored.type == original.type
|
||||
assert restored.type == original.type
|
||||
|
||||
|
||||
class TestWindowsCompatibility:
|
||||
"""Tests for Windows compatibility (signals not available on Windows)."""
|
||||
|
||||
def test_system_events_imports_when_optional_signals_missing(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""system_events should import even if some signals are missing (Windows-like).
|
||||
|
||||
This is a regression test for GitHub issue #4062.
|
||||
"""
|
||||
import importlib
|
||||
|
||||
import crewai.events.types.system_events as system_events_module
|
||||
|
||||
# Simulate a Windows-like signal module by removing optional signals
|
||||
monkeypatch.delattr(signal, "SIGHUP", raising=False)
|
||||
monkeypatch.delattr(signal, "SIGTSTP", raising=False)
|
||||
monkeypatch.delattr(signal, "SIGCONT", raising=False)
|
||||
|
||||
# Reload after patching so class definitions see the modified signal module
|
||||
reloaded = importlib.reload(system_events_module)
|
||||
|
||||
# Import should succeed and enum members should exist
|
||||
assert hasattr(reloaded.SignalType, "SIGHUP")
|
||||
assert hasattr(reloaded.SignalType, "SIGTSTP")
|
||||
assert hasattr(reloaded.SignalType, "SIGCONT")
|
||||
|
||||
# Event classes should still be importable
|
||||
assert hasattr(reloaded, "SigHupEvent")
|
||||
assert hasattr(reloaded, "SigTStpEvent")
|
||||
assert hasattr(reloaded, "SigContEvent")
|
||||
|
||||
# Fallback values should be negative (to avoid conflicts with real signals)
|
||||
assert reloaded.SignalType.SIGHUP < 0
|
||||
assert reloaded.SignalType.SIGTSTP < 0
|
||||
assert reloaded.SignalType.SIGCONT < 0
|
||||
|
||||
def test_signal_events_can_be_created_when_signals_missing(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Signal events should be creatable even when signals are missing.
|
||||
|
||||
This is a regression test for GitHub issue #4062.
|
||||
"""
|
||||
import importlib
|
||||
|
||||
import crewai.events.types.system_events as system_events_module
|
||||
|
||||
# Simulate a Windows-like signal module
|
||||
monkeypatch.delattr(signal, "SIGHUP", raising=False)
|
||||
monkeypatch.delattr(signal, "SIGTSTP", raising=False)
|
||||
monkeypatch.delattr(signal, "SIGCONT", raising=False)
|
||||
|
||||
# Reload after patching
|
||||
reloaded = importlib.reload(system_events_module)
|
||||
|
||||
# Events should be creatable
|
||||
hup_event = reloaded.SigHupEvent()
|
||||
assert hup_event.type == "SIGHUP"
|
||||
|
||||
tstp_event = reloaded.SigTStpEvent()
|
||||
assert tstp_event.type == "SIGTSTP"
|
||||
|
||||
cont_event = reloaded.SigContEvent()
|
||||
assert cont_event.type == "SIGCONT"
|
||||
|
||||
Reference in New Issue
Block a user