Skip to content

Instantly share code, notes, and snippets.

@olistik
Last active August 22, 2017 14:05
Show Gist options
  • Save olistik/fe93d26e29c3a1417ca462d415610b4e to your computer and use it in GitHub Desktop.
Save olistik/fe93d26e29c3a1417ca462d415610b4e to your computer and use it in GitHub Desktop.
Starts and stops Puma using `wait` to wait for the process to quit

I made this because I'm not comfortable relying only on a check of the existence of a process associated with the PID contained in the PID file. I know that exhausting the PID stack is highly unlikely but it's not impossible and I like to make fewer assumptions.

You can spawn Puma with ./spawn.sh and in another shell, simulate a stop with ./stop.sh. After the Puma process stops, a "gate file" gets created, simulating the notification of the end of the process. Using the gate file it's possible to wait for its creation right after having sent the SIGTERM signal but other type of notifications are possible.

I tested this code on OpenBSD 6.1 amd64.

#!/usr/bin/env bash
set -e
APP_PATH="/var/www/apps/my_app"
RELEASE_PATH="$APP_PATH/current"
PID_FILE="$APP_PATH/puma.pid"
GATE_FILE="$APP_PATH/stopped"
SOCKET_FILE="$APP_PATH/puma.socket"
# resets initial conditions. It shouldn't be needed but doing it anyway just in case.
rm -f $PIDFILE $GATEFILE
cd $RELEASE_PATH
# starts the application server
echo "Starts the application server in background"
# puts it in background by appending "&" instead of relying on the "--daemon" flag because the latter doesn't create a child process and is therefore not compatible with `wait`
bundle exec puma --bind "unix://$SOCKET_FILE" --pidfile $PID_FILE --preload --workers 2 --threads 16:16 &
echo "Wait for the PID file to be created"
# should use a counter so that we exit the loop after a timeout
while true; do
if [ -e $PID_FILE ]; then
echo "Created, exiting the wait loop"
break
fi
echo "Sleeping for 1 second"
sleep 1
done
app_pid=$(cat $PID_FILE)
echo "Application PID is $app_pid"
echo "Waiting for app to terminate"
wait $app_pid
# here we wait for the Puma process to receive the SIGTERM
echo "Creating gate file (could invoke any other callback if needed)"
touch $GATE_FILE
#!/usr/bin/env bash
set -e
APP_PATH="/var/www/apps/my_app"
PID_FILE="$APP_PATH/puma.pid"
app_pid=$(cat $PID_FILE)
kill -SIGTERM $app_pid
-bash-4.4$ ./spawn.sh
Starts the application server in background
Wait for the PID file to be created
Sleeping for 1 second
[65206] Puma starting in cluster mode...
[65206] * Version 3.9.1 (ruby 2.4.1-p111), codename: Private Caller
[65206] * Min threads: 16, max threads: 16
[65206] * Environment: development
[65206] * Process workers: 2
[65206] * Preloading application
Sleeping for 1 second
[65206] * Listening on unix:///var/www/apps/my_app/puma.socket
[65206] Use Ctrl-C to stop
[65206] - Worker 0 (pid: 9614) booted, phase: 0
[65206] - Worker 1 (pid: 71756) booted, phase: 0
Created, exiting the wait loop
Application PID is 65206
Waiting for app to terminate
[65206] - Gracefully shutting down workers...
[65206] === puma shutdown: 2017-08-07 11:06:46 +0200 ===
[65206] - Goodbye!
Creating gate file (could invoke any other callback if needed)
-bash-4.4$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment