mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 13:51:09 -05:00
- Added EntitySuggestionManager.vue to manage entity suggestions and authentication. - Created EntitySuggestionModal.vue for displaying suggestions and adding new entities. - Integrated AuthManager for user authentication within the suggestion modal. - Enhanced signal handling in start-servers.sh for graceful shutdown of servers. - Improved server startup script to ensure proper cleanup and responsiveness to termination signals. - Added documentation for signal handling fixes and usage instructions.
202 lines
6.7 KiB
Markdown
202 lines
6.7 KiB
Markdown
# Signal Handling Fix for start-servers.sh
|
|
|
|
## Problem Description
|
|
|
|
The [`start-servers.sh`](../../scripts/start-servers.sh) script was not properly responding to Ctrl+C (SIGINT) signals, causing the script to continue running even after the user attempted to stop it. This left background server processes running and made it difficult to gracefully shut down the development environment.
|
|
|
|
## Root Causes Identified
|
|
|
|
1. **Late Signal Trap Registration**: Signal traps were only registered in the `wait_for_servers()` function after all servers had started, leaving a window during startup where Ctrl+C wouldn't work.
|
|
|
|
2. **No Signal Handling During Startup**: The entire initialization and server startup process had no signal traps, making the script unresponsive to interruption during these phases.
|
|
|
|
3. **Background Process Signal Issues**: Background processes weren't properly configured to receive termination signals from the parent script.
|
|
|
|
4. **No Recursive Signal Prevention**: Multiple signal calls could interfere with graceful shutdown.
|
|
|
|
5. **Inefficient Signal Detection**: The monitoring loop used longer sleep intervals, making signal response less responsive.
|
|
|
|
## Changes Made
|
|
|
|
### 1. Early Signal Trap Registration
|
|
|
|
**Location**: `main()` function, line ~463
|
|
|
|
**Before**:
|
|
```bash
|
|
main() {
|
|
print_status "ThrillWiki Server Start Script Starting..."
|
|
print_status "This script works whether servers are currently running or not."
|
|
print_status "Project root: $PROJECT_ROOT"
|
|
|
|
# Validate project structure
|
|
validate_project
|
|
```
|
|
|
|
**After**:
|
|
```bash
|
|
main() {
|
|
print_status "ThrillWiki Server Start Script Starting..."
|
|
print_status "This script works whether servers are currently running or not."
|
|
print_status "Project root: $PROJECT_ROOT"
|
|
|
|
# Set up signal traps EARLY - before any long-running operations
|
|
print_status "Setting up signal handlers for graceful shutdown..."
|
|
trap 'graceful_shutdown' INT TERM
|
|
|
|
# Validate project structure
|
|
validate_project
|
|
```
|
|
|
|
### 2. Prevent Recursive Signal Handling
|
|
|
|
**Location**: `graceful_shutdown()` function, line ~53
|
|
|
|
**Before**:
|
|
```bash
|
|
graceful_shutdown() {
|
|
if [ "$CLEANUP_PERFORMED" = true ]; then
|
|
return 0
|
|
fi
|
|
|
|
CLEANUP_PERFORMED=true
|
|
|
|
print_warning "Received shutdown signal - performing graceful shutdown..."
|
|
```
|
|
|
|
**After**:
|
|
```bash
|
|
graceful_shutdown() {
|
|
if [ "$CLEANUP_PERFORMED" = true ]; then
|
|
return 0
|
|
fi
|
|
|
|
CLEANUP_PERFORMED=true
|
|
|
|
print_warning "Received shutdown signal - performing graceful shutdown..."
|
|
|
|
# Disable further signal handling to prevent recursive calls
|
|
trap - INT TERM
|
|
```
|
|
|
|
### 3. Improved Background Process Signal Handling
|
|
|
|
**Location**: `start_backend()` and `start_frontend()` functions
|
|
|
|
**Backend Changes** (line ~227):
|
|
```bash
|
|
uv run python manage.py runserver_plus 8000 --verbosity=2 &
|
|
BACKEND_PID=$!
|
|
|
|
# Make sure the background process can receive signals
|
|
disown -h "$BACKEND_PID" 2>/dev/null || true
|
|
```
|
|
|
|
**Frontend Changes** (line ~260):
|
|
```bash
|
|
pnpm vite --port 5173 --open --host localhost --debug &
|
|
FRONTEND_PID=$!
|
|
|
|
# Make sure the background process can receive signals
|
|
disown -h "$FRONTEND_PID" 2>/dev/null || true
|
|
```
|
|
|
|
### 4. Streamlined wait_for_servers() Function
|
|
|
|
**Location**: `wait_for_servers()` function, line ~528
|
|
|
|
**Before**:
|
|
```bash
|
|
wait_for_servers() {
|
|
# Set up signal traps only after servers are successfully running
|
|
print_status "Setting up signal handlers for graceful shutdown..."
|
|
trap 'graceful_shutdown' INT TERM
|
|
|
|
print_status "🚀 Servers are running! Press Ctrl+C for graceful shutdown."
|
|
print_status "📋 Backend: http://localhost:8000 | Frontend: http://localhost:5173"
|
|
|
|
# Keep the script alive and wait for signals
|
|
while [ "$CLEANUP_PERFORMED" != true ]; do
|
|
# Check if both servers are still running
|
|
if [ -n "$BACKEND_PID" ] && ! kill -0 "$BACKEND_PID" 2>/dev/null; then
|
|
print_error "Backend server has stopped unexpectedly"
|
|
graceful_shutdown
|
|
fi
|
|
|
|
if [ -n "$FRONTEND_PID" ] && ! kill -0 "$FRONTEND_PID" 2>/dev/null; then
|
|
print_error "Frontend server has stopped unexpectedly"
|
|
graceful_shutdown
|
|
fi
|
|
|
|
sleep 2
|
|
done
|
|
}
|
|
```
|
|
|
|
**After**:
|
|
```bash
|
|
wait_for_servers() {
|
|
print_status "🚀 Servers are running! Press Ctrl+C for graceful shutdown."
|
|
print_status "📋 Backend: http://localhost:8000 | Frontend: http://localhost:5173"
|
|
|
|
# Keep the script alive and wait for signals
|
|
while [ "$CLEANUP_PERFORMED" != true ]; do
|
|
# Check if both servers are still running
|
|
if [ -n "$BACKEND_PID" ] && ! kill -0 "$BACKEND_PID" 2>/dev/null; then
|
|
print_error "Backend server has stopped unexpectedly"
|
|
graceful_shutdown
|
|
break
|
|
fi
|
|
|
|
if [ -n "$FRONTEND_PID" ] && ! kill -0 "$FRONTEND_PID" 2>/dev/null; then
|
|
print_error "Frontend server has stopped unexpectedly"
|
|
graceful_shutdown
|
|
break
|
|
fi
|
|
|
|
# Use shorter sleep and check for signals more frequently
|
|
sleep 1
|
|
done
|
|
}
|
|
```
|
|
|
|
## Benefits of the Fix
|
|
|
|
1. **Immediate Signal Response**: Ctrl+C now works immediately at any point during script execution, including during startup.
|
|
|
|
2. **Proper Cleanup**: All background processes are properly terminated when the script receives a signal.
|
|
|
|
3. **No Orphaned Processes**: The `disown -h` command ensures background processes receive signals while preventing shell job control interference.
|
|
|
|
4. **Faster Response**: Reduced sleep interval from 2 to 1 second makes signal handling more responsive.
|
|
|
|
5. **Robust Error Handling**: Prevents recursive signal calls and ensures cleanup only happens once.
|
|
|
|
## Testing
|
|
|
|
The fix was validated by:
|
|
- Running syntax validation: `bash -n shared/scripts/start-servers.sh` (passed)
|
|
- Ensuring script permissions are correct: `chmod +x shared/scripts/start-servers.sh`
|
|
|
|
## Usage
|
|
|
|
The script now properly responds to Ctrl+C at any time during execution:
|
|
|
|
```bash
|
|
./shared/scripts/start-servers.sh
|
|
# Press Ctrl+C at any time for graceful shutdown
|
|
```
|
|
|
|
The script will:
|
|
1. Display "Received shutdown signal - performing graceful shutdown..."
|
|
2. Stop the backend server (Django with runserver_plus)
|
|
3. Stop the frontend server (Vite)
|
|
4. Clean up PID files
|
|
5. Exit gracefully
|
|
|
|
## Technical Notes
|
|
|
|
- Signal traps are set early in the `main()` function before any long-running operations
|
|
- The `disown -h` command removes background processes from job control while keeping them as child processes that can receive signals
|
|
- The `trap - INT TERM` command in `graceful_shutdown()` prevents recursive signal handling
|
|
- The monitoring loop includes explicit `break` statements to exit cleanly after cleanup |