Search code examples
bashdebiandaemonsystemd

Getting the exit code of an application launched via startx


I'm setting up Debian so that it works in kiosk mode. To do this, I created a service that performs the watchdog function:

[Unit]
Description=Watchdog for myapp
After=getty@tty7.service 
After=polkit.service
After=udisks2.service 

[Service]
ExecStartPre=systemctl stop dm
ExecStart=su user -c "startx /opt/myapp-watchdog.sh -- :0 vt7"
ExecStop=systemctl start dm
Type=simple
Restart=on-failure
StartLimitInterval=60s
StartLimitBurst=5
RuntimeMaxSec=infinity
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/user/.Xauthority"
Environment="XDG_VTNR=7"

[Install]
WantedBy=graphical.target

The problem is that ExecStart gets the exit code not from myapp, but from startx. I have tried many options, but I have not been able to come up with a way that would work as it should...

I tried trying to pass exit code through pipe, exit &? and writing the exit code to a file. But, apparently, my skills in bash are not enough to make the right command.

Googling also didn't help because to find a case in which people call starts directly from the root, and not from the user, which is why the transfer of exit code is much easier than in my case


Solution

  • Figured it out. It is impossible to solve this problem by means of startx (proof: Link to the xserver error on gitlab). I had to invent bicycles and use crutches.

    The solution is for the service to run a script in which the software is run in a loop. After that, the software exit code is checked. If the code is 0, then the script completes its work. Otherwise, the next iteration of the loop is started. The code below implements a mechanism for exiting this cycle if the software was completed incorrectly 5 or more times in the last minute after the first emergency exit.

    Service code:

    [Unit]
    Description=Watchdog for myapp
    After=getty@tty7.service 
    After=polkit.service
    After=udisks2.service 
    
    [Service]
    ExecStartPre=systemctl stop dm
    ExecStart=su user -c "startx /opt/myapp-watchdog.sh -- :0 vt7"
    ExecStop=systemctl start dm
    Type=simple
    Restart=on-failure
    StartLimitInterval=60s
    StartLimitBurst=5
    RuntimeMaxSec=infinity
    Environment="DISPLAY=:0"
    Environment="XAUTHORITY=/home/user/.Xauthority"
    Environment="XDG_VTNR=7"
    
    [Install]
    WantedBy=graphical.target
    

    Service script code:

    #!/bin/bash
    
    RETURN_VALUE="1"
    RESET_COUNTER=0
    RESET_COUNTER_TIME=0
    TIME_NOW=0
    
    echo "myapp-watchdog: myapp-watchdog started"
    while [ $RETURN_VALUE != "0" ]
    do
        echo "myapp-watchdog: myapp started"
        /opt/myapp
        RETURN_VALUE=$?
        TIME_NOW=$(date +"%s")
        if [ $RETURN_VALUE == "0" ]
        then
            echo "myapp-watchdog: myapp exited with code 0"
            echo "myapp-watchdog: myapp-watchdog finished"
            exit 0
        else
            if [[ $TIME_NOW -gt $RESET_COUNTER_TIME ]]
            then
                RESET_COUNTER=0
            fi
            if [ $RESET_COUNTER == 0 ]
            then
                RESET_COUNTER_TIME=$TIME_NOW+60
            fi
            
            RESET_COUNTER=$((RESET_COUNTER + 1))
            echo "myapp-watchdog: abnormal exit code detected. Current number of errors in the last minute: $RESET_COUNTER"
            
            if [ $RESET_COUNTER == 5 ]
            then
                echo "myapp-watchdog: myapp exited with code 1"
                    echo "myapp-watchdog: myapp-watchdog finished"
                exit 1
            fi
        fi
    done