Vinanrra
Vinanrra

Reputation: 83

Trap docker signal and stop process in bash not working

I have already read and try this

I'm not able to gracefully stop my docker container, the container just stop and kill everything inside instead of run my trap handler, I have been trying to solve this 1 year or more.

This is my entrypoint

ENTRYPOINT ["/home/sdtdserver/user.sh", "/home/sdtdserver/install.sh"]

This is one of the script that do preparations and then continue to other, user.sh

    #!/bin/bash
    exit_handler() {
            # Execute the  shutdown commands
            echo "[INFO] Stopping 7 Days To Die Server" >> /home/sdtdserver/log/console/sdtdserver-console.log
            su-exec sdtdserver /home/sdtdserver/sdtdserver stop
            exit
    }
    
    set -eu
    
    # Print info
    echo "
            =======================================================================
            USER INFO:
    
            UID: $PUID
            GID: $PGID
    
            MORE INFO:
    
            If you have permission problems remember to use same user UID and GID.
            Check it with "id" command
            If problem persist check:
            https://github.com/vinanrra/Docker-7DaysToDie/blob/master/README.md
            =======================================================================
    "
    
    # Set user and group ID to sdtdserver user
    groupmod -o -g "$PGID" sdtdserver  > /dev/null 2>&1
    usermod -o -u "$PUID" sdtdserver  > /dev/null 2>&1
    
    # Locale, Timezone
    localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && \
    ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone
    
    # Apply owner to the folder to avoid errors
    chown -R sdtdserver:sdtdserver /home/sdtdserver
    
    # Start cron
    service cron start
    
    # Change user to sdtdserver
    su-exec sdtdserver "$@"
    
    # Trap specific signals and forward to the exit handler
    trap exit_handler SIGTERM
    
    # Keep script alive to trap SIGTERM
    while true; do
            sleep 10
    done

I think my problem come here: su-exec sdtdserver "$@" - Line 43

I'm using su-exec to execute the swap the user and execute the next scripts as other user, and maybe that's the problem, I have been thinking too to move the user.sh script to somewhere where the script will be executed when it's started without using the entrypoint in the Dockerfile and instead swap to my other script install.sh and even remove the use of su-exec and reformat everything in one script (I don't like this idea tbh)

#!/bin/bash
rootDir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
scriptsDir="${rootDir}/scripts"

# Show log function
show_log () {
   i="0"
      # -F = --follow=name --retry
      tail -F /home/sdtdserver/log/console/sdtdserver-console.log
}

test_alert () {
   if [ "${TEST_ALERT,,}" == 'yes'  ]; then
      source $scriptsDir/server_alerts.sh
   fi
}

# Check requeriments

# Check if script is missing
if [ ! -f sdtdserver ]; then
   source $scriptsDir/check_script.sh
fi

# Check if server have been installed
if [ ! -f serverfiles/DONT_REMOVE.txt ]; then
   source $scriptsDir/first_install.sh
fi

# Crontab
echo "# Crontab file" > crontab.txt

if [ "${BACKUP,,}" == 'yes'  ]; then
   source $scriptsDir/crontab/backup.sh
fi

if [ "${MONITOR,,}" == 'yes'  ]; then
   source $scriptsDir/crontab/monitor.sh
fi

echo "# Don't remove the empty line at the end of this file. It is required to run the cron job" >> crontab.txt

crontab crontab.txt

rm crontab.txt

# Use of case to avoid errors if used wrong START_MODE
case $START_MODE in
   0)
      exit
   ;;
   1)
      source $scriptsDir/server_start.sh
      test_alert
      show_log
   ;;
   2)
      source $scriptsDir/server_update.sh
      exit
   ;;
   3)
      source $scriptsDir/server_update.sh
      source $scriptsDir/server_start.sh
      test_alert
      show_log
   ;; 
   4)
      source $scriptsDir/server_backup.sh
      exit
   ;;
   *)
      source $scriptsDir/check_startMode.sh
      exit
   ;;
esac

This is top command inside the container:

TOP-Command

This is the GitHub branch where I'm doing the testing: fix-exit

First thanks to everyone that try to help me and second I just don't want to copy and paste a code, I want to understand why isn't working, because that's the issue I have, I'm clueless and that's why I'm unable to fix it, even documentation it's appreciated.

Upvotes: 3

Views: 2113

Answers (1)

Vinanrra
Vinanrra

Reputation: 83

The problem was that I wasn't running the script asynchronous, and bash was waiting to end the tail command at the end of install.sh (which was "endless"), here is the part of the code that was changed:

# Change user to sdtdserver
su-exec sdtdserver bash /home/sdtdserver/install.sh &
# If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.
# When bash is waiting for an asynchronous command via the wait builtin,
# the reception of a signal for which a trap has been set will cause the 'wait' builtin to return immediately with an exit status greater than 128,
# immediately after which the trap is executed.
wait $!

Also, this man had the same problem, but I didn't know that the tail was the problem.

SIGTERM signal not caught when the last process is tail

Upvotes: 4

Related Questions