Skip to content

Instantly share code, notes, and snippets.

@alazycoder101
Created November 26, 2024 22:49
Show Gist options
  • Save alazycoder101/3e0d2a4c6a9da6146b32882aa35fafbd to your computer and use it in GitHub Desktop.
Save alazycoder101/3e0d2a4c6a9da6146b32882aa35fafbd to your computer and use it in GitHub Desktop.

Mastering Linux Kill Signals: Graceful Shutdown in Containerized Worker Environments

Introduction to Linux Kill Signals

Linux kill signals are a crucial mechanism for process communication and management. These signals provide a way to send specific instructions to processes, with each signal representing a different type of communication or action.

Common Kill Signals

Signal Name Description Default Action
SIGTERM (15) Terminate Graceful shutdown request Terminate process
SIGKILL (9) Kill Forceful termination Immediately stop process
SIGINT (2) Interrupt Interrupt from keyboard (Ctrl+C) Terminate process
SIGHUP (1) Hangup Reload configuration or terminate Terminate process

Kill Signals in Containerized Environments

In containerized environments, proper handling of kill signals is critical to ensure:

  • Graceful shutdown of worker processes
  • Completion of in-progress jobs
  • Proper resource cleanup
  • Minimal service disruption

Sidekiq Worker Signal Handling

Sidekiq provides robust signal handling for graceful shutdowns:

# Example Sidekiq signal handling
Sidekiq.configure_server do |config|
  config.on(:shutdown) do
    # Perform cleanup operations
    puts "Gracefully shutting down Sidekiq"
  end
end

Laravel Worker Signal Management

Laravel workers can implement graceful shutdown mechanisms:

// Laravel worker signal handling
public function handle()
{
    // Register signal handlers
    pcntl_signal(SIGTERM, function () {
        $this->shouldStop = true;
    });

    while (!$this->shouldStop) {
        // Process jobs
        $this->processNextJob();
    }
}

Grace Period Implementation

Grace periods are crucial for ensuring uninterrupted job processing:

Docker Compose Example

services:
  worker:
    stop_grace_period: 30s  # 30-second grace period
    stop_signal: SIGTERM    # Use graceful termination

Kubernetes Deployment Configuration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: worker-deployment
spec:
  template:
    spec:
      containers:
      - name: worker
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 30"]

Supervisord: Signal Management and Process Control

Supervisord provides a robust solution for managing long-running processes and handling signal propagation in containerized environments.

Signal Propagation Workflow

When a container receives a termination signal, the process flow typically looks like this:

Container Termination Signal (SIGTERM)
│
↓
Supervisord
│
↓
Supervised Processes
│
↓
Application Graceful Shutdown

Supervisord Configuration Example

[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid

[program:worker]
command=/usr/bin/php /app/artisan queue:work
autostart=true
autorestart=true
stopwaitsecs=30
stopsignal=SIGTERM
stopasgroup=true
killasgroup=true

[program:sidekiq-worker]
command=bundle exec sidekiq
autostart=true
autorestart=true
stopwaitsecs=30
stopsignal=SIGTERM
stopasgroup=true
killasgroup=true

Docker Compose Integration

services:
  app:
    build: .
    volumes:
      - ./supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
    stop_signal: SIGTERM
    stop_grace_period: 45s

Comprehensive Signal Handling Script

#!/bin/bash

# Trap SIGTERM signal
trap_sigterm() {
    echo "Received SIGTERM. Initiating graceful shutdown..."
    
    # Notify Supervisord to stop workers
    supervisorctl stop all
    
    # Wait for processes to shut down
    wait_for_workers_shutdown
    
    # Perform any additional cleanup
    cleanup_resources
    
    exit 0
}

wait_for_workers_shutdown() {
    timeout=30
    while [ $timeout -gt 0 ]; do
        active_workers=$(supervisorctl status | grep -E "RUNNING|STARTING" | wc -l)
        if [ $active_workers -eq 0 ]; then
            echo "All workers have shutdown successfully"
            return 0
        fi
        sleep 1
        ((timeout--))
    done
    
    echo "Some workers did not shutdown in time"
    return 1
}

cleanup_resources() {
    # Example: Clear temporary files, close database connections
    rm -rf /tmp/worker-*
    echo "Cleanup complete"
}

# Attach the trap
trap trap_sigterm SIGTERM

# Start Supervisord
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf

Advanced Signal Handling Considerations

Multi-Process Signal Propagation

  1. Parent Process Responsibility: Supervisord acts as a parent process managing child processes
  2. Signal Forwarding: Uses stopasgroup=true and killasgroup=true to ensure signal propagation
  3. Graceful Termination Sequence:
    • Receive SIGTERM
    • Notify all child processes
    • Wait for processes to complete
    • Force terminate if grace period expires

Kubernetes Integration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  template:
    spec:
      containers:
      - name: app
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "supervisorctl stop all"]

Potential Pitfalls and Solutions

  1. Zombie Processes: Use init systems or containers with proper PID 1 management
  2. Incomplete Shutdown: Implement robust timeout mechanisms
  3. Resource Leaks: Always include cleanup scripts

Best Practices for Signal Handling

  • Use stopsignal=SIGTERM in Supervisord
  • Implement proper timeout mechanisms
  • Log all shutdown and cleanup activities
  • Test signal handling thoroughly in staging environments

Conclusion

Effective signal management with Supervisord provides a robust mechanism for graceful process termination, ensuring minimal disruption and proper resource management in containerized environments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment