FINAL_CRASH_FIX_SUMMARY.md•3.84 kB
# Final FreeCAD AI Addon Crash Fix Summary
## Overview
Successfully fixed all crash issues in the FreeCAD AI addon. The addon now loads and runs stably without segmentation faults.
## Summary of All Fixes Applied
### 1. QTimer.singleShot Crashes (15 occurrences fixed)
**Issue**: QTimer.singleShot calls with lambda functions were causing segmentation faults during workbench switching.
**Files Fixed**:
- `freecad-ai/gui/providers_widget.py` (4 occurrences)
- `freecad-ai/gui/connection_widget.py` (2 occurrences)
- `freecad-ai/gui/unified_connection_widget.py` (6 occurrences)
- `freecad-ai/gui/agent_control_widget.py` (1 occurrence)
- `freecad-ai/gui/conversation_widget.py` (1 occurrence)
- `freecad-ai/gui/server_widget.py` (1 occurrence)
**Solution**: Replaced all `QTimer.singleShot(delay, lambda: method())` calls with direct `method()` calls.
### 2. AttributeError: 'status_label' not found
**Issue**: Signal handlers were being called before the UI was fully initialized, trying to access `self.status_label` before it existed.
**File Fixed**: `freecad-ai/gui/main_widget.py`
**Solution**: Added `hasattr(self, "status_label")` checks in all signal handlers:
- `_on_provider_status_changed()`
- `_on_providers_updated()`
- `_on_agent_mode_changed()`
- `_on_agent_state_changed()`
### 3. Qt Signal Creation During Workbench Activation
**Issue**: The most critical issue - Qt signals were being created at module import time, causing crashes during workbench activation.
**File Fixed**: `freecad-ai/ai/provider_integration_service.py`
**Root Cause**:
- `ProviderIntegrationService` was inheriting from `QtCore.QObject`
- Qt signals were being defined as class attributes
- PySide2 was imported at module level
- This caused Qt object creation during workbench switching, before Qt was ready
**Solution**: Complete refactoring to remove all Qt dependencies:
1. Removed PySide2 import at module level
2. Removed inheritance from QtCore.QObject
3. Removed Qt Signal definitions
4. Implemented a pure Python callback-based system that mimics Qt's signal/slot interface
5. Created signal-like properties that return callback handlers with `connect()` and `emit()` methods
### 4. Provider Service Initialization Timing
**File Fixed**: `freecad-ai/gui/main_widget.py`
**Changes**:
- Moved provider initialization from `_setup_provider_service()` to `_final_connection_check()`
- Added `enable_signals()` call before provider initialization
- Ensures providers are only initialized after the UI is completely ready
## Technical Details
### The Callback System
The new callback system in `provider_integration_service.py` provides a Qt-signal-like interface without any Qt dependencies:
```python
@property
def provider_added(self):
"""Signal-like interface for provider_added callbacks."""
class CallbackSignal:
def connect(self, callback):
# Add callback to list
def emit(self, *args):
# Call all callbacks
return CallbackSignal(self.provider_added_callbacks)
```
This allows the existing code to use the familiar `signal.connect()` and `signal.emit()` pattern without requiring Qt.
## Result
- FreeCAD starts without crashes
- Workbench switching works properly
- All UI components load correctly
- Provider service initialization works as expected
- No segmentation faults
## Key Learnings
1. **Never use QTimer.singleShot with lambda functions in FreeCAD addons** - they cause crashes during widget initialization
2. **Never inherit from QObject or use Qt signals during module import** - Qt must be fully initialized first
3. **Always check for UI element existence before using them in callbacks** - signals may fire before UI is ready
4. **Defer all Qt-related initialization until after workbench activation** - use callback systems for early initialization