Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sending SIGUSR2 with resque:workers terminates parent #1839

Open
schnittchen opened this issue Oct 11, 2022 · 1 comment
Open

sending SIGUSR2 with resque:workers terminates parent #1839

schnittchen opened this issue Oct 11, 2022 · 1 comment

Comments

@schnittchen
Copy link

The same probably holds for other signals. It would make sense to delegate those signals intended at controlling the workers to the worker processes, instead of crashing.

This would also be very helpful for wrapping resque in a systemd service.

rake aborted!
SignalException: SIGUSR2
SOME_PATH/ruby/3.1.0/gems/resque-2.4.0/lib/resque/tasks.rb:37:in `join'
SOME_PATH/ruby/3.1.0/gems/resque-2.4.0/lib/resque/tasks.rb:37:in `block (3 levels) in <main>'
SOME_PATH/ruby/3.1.0/gems/resque-2.4.0/lib/resque/tasks.rb:37:in `each'
SOME_PATH/ruby/3.1.0/gems/resque-2.4.0/lib/resque/tasks.rb:37:in `block (2 levels) in <main>'
SOME_PATH/ruby/3.1.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
Tasks: TOP => resque:workers
(See full trace by running task with --trace)
@schnittchen
Copy link
Author

Here's the wrapper script I use to make rake resque:workers co-operate with systemd. It might be useful beyond that.

No guarantee this doesn't kill kittens.

#!/bin/bash

set -euo pipefail

bundle exec rake resque:workers &

child=$!

# We need to delegate some signals to the workers,
# see https://github.com/resque/resque/issues/1839
#
# This code assumes that the children of the rake task
# (our grandchildren) are all workers.
#
# The rake task will exit when all workers have exited.

function kill_grandchildren() {
  local signal=$1

  for grandchild in $(cat /proc/$child/task/*/children); do
    kill -s $signal $grandchild
  done
}

inhibit_continue=

# Comments are quotes from the resque Readme;
# they are from the perspective of a worker process

#    QUIT - Wait for child to finish processing then exit
function handle_SIGQUIT() {
  # See systemd.kill(5).
  # Systemd sends a SIGCONT right after the KillSignal (SIGQUIT in our case), which we prevent from propagating.
  inhibit_continue=1

  kill_grandchildren SIGQUIT
}
trap handle_SIGQUIT SIGQUIT

#    TERM / INT - Immediately kill child then exit
function handle_SIGTERM() {
  kill_grandchildren SIGTERM
}
trap handle_SIGTERM SIGTERM SIGINT

#    USR1 - Immediately kill child but don't exit
function handle_SIGUSR1() {
  kill_grandchildren SIGUSR1
}
trap handle_SIGUSR1 SIGUSR1

#    USR2 - Don't start to process any new jobs
function handle_SIGUSR2() {
  kill_grandchildren SIGUSR2
}
trap handle_SIGUSR2 SIGUSR2

#    CONT - Start to process new jobs again after a USR2
function handle_SIGCONT() {
  if [ "$inhibit_continue" = "" ]; then
    kill_grandchildren SIGCONT
  fi
}
trap handle_SIGCONT SIGCONT


while :; do
    set +e
    wait $child
    status=$?
    set -e

    if [[ $status > 128 ]]; then
      # ignore signals
      true
    else
      # "delegate" child status up
      exit $status
    fi
done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant