Skip to content

Commit 55f5d9c

Browse files
committed
feat(runner): add graceful shutdown handling
- Implements signal handlers for SIGTERM and SIGINT to ensure the container properly stops running jobs and cleans up runner registrations. - Introduces a cleanup process that prevents orphaned runner entries, enhancing container management and reliability during shutdowns. - Captures the runner process PID to manage its termination effectively.
1 parent f143979 commit 55f5d9c

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ docker run -d \
8686
The following environment variables are set in the Docker image:
8787
- `DOTNET_INSTALL_DIR`: Set to `/home/runner/.dotnet` to avoid permission issues when using actions/setup-dotnet
8888

89+
#### Graceful Shutdown
90+
The container handles shutdown signals (SIGTERM, SIGINT) gracefully:
91+
- Stops the running job (if any)
92+
- Removes the runner registration from GitHub
93+
- Ensures clean termination
94+
95+
This automatic cleanup prevents orphaned runner registrations when containers are stopped.
96+
8997
## Included Software
9098

9199
### Pre-installed in Base Image

src/entrypoint.sh

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,64 @@ set -e
44
# Switch to runner user home directory
55
cd /home/runner
66

7+
# Global variable to track if we're shutting down
8+
SHUTTING_DOWN=false
9+
10+
# Signal handler for graceful shutdown
11+
handle_shutdown() {
12+
local signal=$1
13+
14+
if [ "$SHUTTING_DOWN" = "true" ]; then
15+
echo "Shutdown already in progress..."
16+
return
17+
fi
18+
19+
SHUTTING_DOWN=true
20+
echo ""
21+
echo "Received $signal signal, cleaning up..."
22+
23+
# Kill the runner process if it's running
24+
if [ -n "$RUNNER_PID" ]; then
25+
echo "Stopping runner process (PID: $RUNNER_PID)..."
26+
kill -TERM "$RUNNER_PID" 2>/dev/null || true
27+
28+
# Wait for the runner to stop (max 30 seconds)
29+
local count=0
30+
while kill -0 "$RUNNER_PID" 2>/dev/null && [ $count -lt 30 ]; do
31+
sleep 1
32+
count=$((count + 1))
33+
done
34+
35+
# Force kill if still running
36+
if kill -0 "$RUNNER_PID" 2>/dev/null; then
37+
echo "Force stopping runner process..."
38+
kill -KILL "$RUNNER_PID" 2>/dev/null || true
39+
fi
40+
fi
41+
42+
# Remove runner configuration
43+
cleanup_runner
44+
45+
echo "Cleanup completed."
46+
47+
# Exit with proper signal code
48+
case "$signal" in
49+
INT)
50+
exit 130 # 128 + 2 (SIGINT)
51+
;;
52+
TERM)
53+
exit 143 # 128 + 15 (SIGTERM)
54+
;;
55+
*)
56+
exit 1
57+
;;
58+
esac
59+
}
60+
61+
# Set up signal handlers with proper exit codes
62+
trap 'handle_shutdown INT' INT
63+
trap 'handle_shutdown TERM' TERM
64+
765
# Function to handle runner cleanup
866
cleanup_runner() {
967
echo "Attempting to remove existing runner configuration..."
@@ -102,9 +160,15 @@ main() {
102160
# Configure the runner
103161
configure_runner
104162

105-
# Start the runner
163+
# Start the runner in background to capture PID
106164
echo "Starting GitHub Actions runner..."
107-
exec ./run.sh
165+
./run.sh &
166+
RUNNER_PID=$!
167+
168+
echo "Runner started with PID: $RUNNER_PID"
169+
170+
# Wait for the runner process
171+
wait $RUNNER_PID
108172
}
109173

110174
# Execute main function

0 commit comments

Comments
 (0)