Fix socket error handling to prevent server crashes on ECONNREFUSED

This commit addresses critical issues where unhandled socket connection errors (ECONNREFUSED) would crash the server and cause memory leaks with rising connection counts.

Changes:
- Add createSocketWithErrorHandler() utility that attaches error handlers immediately upon socket creation
- Update https-passthrough-handler to use safe socket creation and clean up client sockets on server connection failure
- Update https-terminate-to-http-handler to use safe socket creation
- Ensure proper connection cleanup when server connections fail
- Document the fix in readme.hints.md and create implementation plan in readme.plan.md

The fix prevents race conditions where sockets could emit errors before handlers were attached, and ensures failed connections are properly cleaned up to prevent memory leaks.
This commit is contained in:
2025-06-01 13:15:50 +00:00
parent 9fdc2d5069
commit d45485985a
6 changed files with 258 additions and 101 deletions

View File

@ -413,4 +413,48 @@ const routes: IRouteConfig[] = [{
### 7. Next Steps (Remaining Work)
- **Phase 2 (cont)**: Migrate components to use LifecycleComponent
- **Phase 3**: Add worker threads for CPU-intensive operations
- **Phase 4**: Performance monitoring dashboard
- **Phase 4**: Performance monitoring dashboard
## Socket Error Handling Fix (v19.5.11+)
### Issue
Server crashed with unhandled 'error' event when backend connections failed (ECONNREFUSED). Also caused memory leak with rising active connection count as failed connections weren't cleaned up properly.
### Root Cause
1. **Race Condition**: In forwarding handlers, sockets were created with `net.connect()` but error handlers were attached later, creating a window where errors could crash the server
2. **Incomplete Cleanup**: When server connections failed, client sockets weren't properly cleaned up, leaving connection records in memory
### Solution
Created `createSocketWithErrorHandler()` utility that attaches error handlers immediately:
```typescript
// Before (race condition):
const socket = net.connect(port, host);
// ... other code ...
socket.on('error', handler); // Too late!
// After (safe):
const socket = createSocketWithErrorHandler({
port, host,
onError: (error) => {
// Handle error immediately
clientSocket.destroy();
},
onConnect: () => {
// Set up forwarding
}
});
```
### Changes Made
1. **New Utility**: `ts/core/utils/socket-utils.ts` - Added `createSocketWithErrorHandler()`
2. **Updated Handlers**:
- `https-passthrough-handler.ts` - Uses safe socket creation
- `https-terminate-to-http-handler.ts` - Uses safe socket creation
3. **Connection Cleanup**: Client sockets destroyed immediately on server connection failure
### Test Coverage
- `test/test.socket-error-handling.node.ts` - Verifies server doesn't crash on ECONNREFUSED
- `test/test.forwarding-error-fix.node.ts` - Tests forwarding handlers handle errors gracefully
### Configuration
No configuration changes needed. The fix is transparent to users.