Can't terminate a process except by a full system shutdown

while using Pipeline to watch a video, cpu usage got high, temperature started reached 100 °C and fans started spinning.

I tried the following:

  • quitting using ctrl+q just shut down the gui but it still ran in the background and resources were still consumed
  • using gnome’s system monitor’s (terminate/stop/force stop) didn’t work either and the process kept running
  • sudo kill -9 PID didn’t work either
  • I logged out of the session and I could still hear the fans still spinning and cpu usage was high, the process didn’t stop either
  • I tried shutting down the pc but it got stuck with systemd trying to terminate the process so I had to press power button for 10 seconds to force shutdown. this seems to be the only way I can stop the running process

here’s how the process looked like before force shutting down the pc:

something similar happened recently while using yazi. while accessing ~/Videos, fans started spinning even after quitting yazi, ffmpeg was still running with a high cpu usage (it was initiated by yazi) and the above methods didn’t work either.

pipeline was installed as a flatpak while yazi was installed through pacman and both faced the same issue. so I guess the problem isn’t specific to a certain program.

any help would be appreciated!

There’s a better way to force shutdown in such cases: REISUB.

BTW, if you don’t use yazi or pipeline, does the problem still occur?

2 Likes

Thanks for the suggestion! But on a laptop keyboard with no SysRq button, what button do I press instead?

The problem only occurs with yazi and pipeline (both used to be fine before). pipeline problem occurs when it plays videos, while yazi’s problem occurs when it enters a folder that has videos. If I avoid that both work normally.

The Print Screen key.

4 Likes

Thank you!

I’d like to add, that you can try using only part of the REISUB command. For example, try ALT+PrtScreen+E or ALT+PrtScreen+I to only send SigTerm or SigKill to kill /terminate all programs… see if that works. The Arch wiki also mentions, that you can try to kill memory hogging processes with ALT+SysRq+F.

Also, for SysRq to work, it has to be enabled in the Kernel. Vanilla Arch has it disabled, so I am fairly sure, EOS has it disabled as well.

You can use sysctl kernel.sysrq=1 in a terminal, to enable it once. To make the changes persistent, you need to edit / create /etc/sysctl.d/99-sysctil.conf. In there you add kernel.sysrq=1. Note that you can name the file something else. Mine is named 99-sysrq.conf. If you want SysRq to be enabled during boot already, you can sysrq_always_enabled or sysrq_always_enabled=1 to your kernel parameters.

You can find more information about SysRq and the commands in the Arch Wiki, here: https://wiki.archlinux.org/title/Keyboard_shortcuts and about sysctl here: https://wiki.archlinux.org/title/Sysctl#Configuration.

Hope this helps. Cheers

1 Like

Did you try :

pkill tubefeeder

EndeavourOS installs and updates the kernels directly from the Arch repos.
And here SysRq seems to work, had to use it a couple of times.

Yes, but what BenJB83 says is that you have to enable support for the Magic key, as by default it isn’t enabled.

1 Like

Sounds like the problem relates to those apps or their dependencies.

True, and that was explained in the REISUB link above.
(Could be a language barrier problem since I’m not a native English speaker.)

Additionally, the Welcome app has a button to enable this feature.

No worries. :slight_smile: All good… Not a native English speaker here either, only fluent. As for the button in the welcome app… I didn’t know about that. I am running Arch itself for a while now, though once it breaks, I’ll probably go back to EndeavourOS.

And yes… if everything else works fine, it’s probably an issue with the packages or one of its dependencies. Maybe check the package page to see if anybody made a comment about this?

2 Likes

Hello everyone, thank you for the very detailed responses! I tested the mentioned solutions but they kinda didn’t exactly work.

here’s what exactly happened:

  1. I enabled SysRq key, tried it first while everything was normal and it seemed to work.
  2. I then proceeded to launch yazi and I encountered the same problem. Here’s what it showed me when I tried to quit it anyway
  3. I tried SysRq REISUB sequence to terminate ffmpeg process and pc rebooted but I saw an fsck check while rebooting so I assumed it didn’t terminate the process gracefully (I generally get an fsck check when I force a shutdown).
  4. After the reboot yazi worked with no problems, the video preloader didn’t get stuck at all.
  5. I rebooted the pc just to make sure but the problem appeared again, I tried pkill ffmpeg as @vazicebon suggested but it didn’t work.
  6. I tried SysRQ+R+E+I and it would get me to GDM login screen but I can’t log in and the fans are still spinning (so the process still didn’t get terminated)
  7. I tried SysRq REISUB in order and it rebooted but still gave me an fsck check again during boot.

As for the possibility of the problems being specific to the packages, I checked the repos issues section and nobody mentioned my problem for either packages so I’m not really sure what’s causing the problem

pkill tubefeeder

it’s the name of your application. :smiley:

I was referring to the stuck process caused by yazi this time which was ffmpeg. Sadly pkill didn’t terminate ffmpeg nor tubefeeder :sweat_smile:

Its for this situation that i wrote this script a while back

View Code #!/bin/bash

Check if required commands are installed

check_dependencies() {
local missing_commands=()
for command in ps grep awk cut read; do
if ! command -v “$command” &> /dev/null; then
missing_commands+=(“$command”)
fi
done

if [ ${#missing_commands[@]} -gt 0 ]; then
    echo "The following commands are required but not found in your PATH:"
    for command in "${missing_commands[@]}"; do
        echo "- $command"
    done
    echo "Please install the missing commands and try again."
    exit 1
fi

}

Function to find near matches for a process name

find_near_matches() {
local process_name=“$1”
local near_matches=$(ps -eo comm | grep -i “$process_name” | awk ‘!seen[$0]++’ | tr ‘\n’ ‘\n’)
echo “$near_matches”
}

Function to get process information by PID

get_process_info() {
local pid=“$1”
local process_info=$(ps -p “$pid” -o comm,cmd --no-headers | head -n 1)
local process_name=$(echo “$process_info” | awk ‘{print $1}’)
local process_path=$(echo “$process_info” | awk ‘{for(i=2;i<=NF;i++) if($i ~ /^//) {print $i; exit}}’)
echo “$process_name” “$process_path”
}

Function to send signal to a process group

send_signal_to_process_group() {
local pids=“$1”
local signal=“$2”
for pid in $pids; do
kill “-$signal” “$pid”
done
}

Function to handle process termination

handle_process_termination() {
local pids=“$1”
local signal=“$2”
local wait_time=“$3”

send_signal_to_process_group "$pids" "$signal"
echo "Signal $signal sent to process group with PIDs: $pids"

# Wait for the specified time to allow signal to be processed
echo "Waiting for $wait_time seconds to allow signal to be processed..."
sleep "$wait_time"

# Check if processes are still running after signal
local still_running_pids=""
for pid in $pids; do
    if ps -p "$pid" -o comm,cmd > /dev/null; then
        still_running_pids+="$pid "
    fi
done

if [ -n "$still_running_pids" ]; then
    echo "The following processes are still running after $wait_time seconds: $still_running_pids"
    echo "Do you want to send a HARD KILL (SIGKILL 9) to these processes? (y/n)"
    read kill_9_signal
    if [ "$kill_9_signal" == "y" ]; then
        send_signal_to_process_group "$still_running_pids" 9
        echo "HARD KILL (SIGKILL 9) sent to process group with PIDs: $still_running_pids"
        echo "Waiting for 2 seconds to allow SIGKILL to be processed..."
        sleep 2
    fi
else
    echo "All processes have terminated successfully."
fi

}

Function to list processes by user

list_processes_by_user() {
local username=“$1”
local processes=$(ps -u “$username” -o pid,user,comm --no-headers)
if [ -n “$processes” ]; then
echo “Processes for user ‘$username’:”
echo “$processes”
else
echo “No processes found for user ‘$username’.”
fi
}

Function to list all users

list_all_users() {
local users=$(cut -d: -f1 /etc/passwd)
echo “Available users:”
counter=1
for user in $users; do
echo “$counter) $user”
counter=$((counter + 1))
done
}

Function to prompt user for kill signal

prompt_kill_signal() {
echo “Do you want to send:”
echo " (y) Soft Kill (SIGTERM 15)"
echo " (k) HARD KILL (SIGKILL 9)"
echo " (c) Cancel"
read -r kill_signal
}

Function to list top 10 processes by CPU usage

list_top_cpu_processes() {
echo “Observing processes for CPU usage…”
top_cpu_processes=$(ps -eo pid,user,comm,%cpu,cmd --sort=-%cpu | head -n 11)
echo “Top 10 processes by CPU usage:”
echo “No. PID USER COMMAND %CPU PATH”
echo “$top_cpu_processes” | awk ‘NR>1 {printf “%2d) %-8s %-10s %-20s %5s %s\n”, NR-1, $1, $2, $3, $4, $5}’

# Allow user to select a process
echo "Enter the number corresponding to the desired process (or 'q' to cancel):"
read -r selection
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le 10 ]; then
    selected_pid=$(echo "$top_cpu_processes" | awk -v sel="$selection" 'NR==sel+1 {print $1}')
    handle_selected_process "$selected_pid"
fi

}

Function to list top 10 processes by memory usage

list_top_memory_processes() {
echo “Observing processes for memory usage…”
top_memory_processes=$(ps -eo pid,user,comm,%mem,cmd --sort=-%mem | head -n 11)
echo “Top 10 processes by memory usage:”
echo “No. PID USER COMMAND %MEM PATH”
echo “$top_memory_processes” | awk ‘NR>1 {printf “%2d) %-8s %-10s %-20s %5s %s\n”, NR-1, $1, $2, $3, $4, $5}’

# Allow user to select a process
echo "Enter the number corresponding to the desired process (or 'q' to cancel):"
read -r selection
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le 10 ]; then
    selected_pid=$(echo "$top_memory_processes" | awk -v sel="$selection" 'NR==sel+1 {print $1}')
    handle_selected_process "$selected_pid"
fi

}

Function to handle the selected process

handle_selected_process() {
local pid=“$1”
if ps -p “$pid” -o comm,cmd > /dev/null; then
# Get the process name and path
IFS=" " read -ra process_info <<< “$(get_process_info “$pid”)”
process_name=“${process_info[0]}”
process_path=“${process_info[1]}”

    echo "Process with PID $pid is running:"
    echo "Name: $process_name"
    echo "Path: $process_path"

    prompt_kill_signal
    if [ "$kill_signal" == "y" ]; then
        echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
        read -r wait_time
        if [ -z "$wait_time" ]; then
            wait_time=5
        fi
        handle_process_termination "$pid" 15 "$wait_time"
    elif [ "$kill_signal" == "k" ]; then
        handle_process_termination "$pid" 9 2
    fi
else
    echo "Process with PID $pid is not running"
fi

}

Check dependencies before running the script

check_dependencies

Prompt the user to enter the PID or process name to check

while true; do
echo “Enter one of the following options:”
echo " - PID: Enter a specific PID to check the process."
echo " - Process Name: Enter a process name to check."
echo " - ‘user’: List processes by user."
echo " - ‘cpu’: List top 10 CPU consuming processes."
echo " - ‘mem’: List top 10 memory consuming processes."
echo " - ‘q’: Quit the program."
read -e input

if [ "$input" == "q" ]; then
    echo "Exiting..."
    break
elif [ "$input" == "user" ]; then
    list_all_users
    echo "Enter the number corresponding to the desired user (or 'q' to cancel):"
    read selection
    if [ "$selection" == "q" ]; then
        continue
    fi
    selected_user=$(cut -d: -f1 /etc/passwd | awk -v sel="$selection" 'NR == sel')
    list_processes_by_user "$selected_user"
elif [ "$input" == "cpu" ]; then
    list_top_cpu_processes
elif [ "$input" == "mem" ]; then
    list_top_memory_processes
else
    # Check if the input is a PID or a process name
    if [[ "$input" =~ ^[0-9]+$ ]]; then
        # Input is a PID
        pid="$input"
        if ps -p "$pid" -o comm,cmd > /dev/null; then
            # Get the process name and path
            IFS=" " read -ra process_info <<< "$(get_process_info "$pid")"
            process_name="${process_info[0]}"
            process_path="${process_info[1]}"

            echo "Process with PID $pid is running:"
            echo "Name: $process_name"
            echo "Path: $process_path"

            prompt_kill_signal
            if [ "$kill_signal" == "y" ]; then
                echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
                read -r wait_time
                if [ -z "$wait_time" ]; then
                    wait_time=5
                fi
                handle_process_termination "$pid" 15 "$wait_time"
            elif [ "$kill_signal" == "k" ]; then
                handle_process_termination "$pid" 9 2
            fi
        else
            echo "Process with PID $pid is not running"
        fi
    else
        # Input is a process name
        process_name="$input"
        pids=$(ps -C "$process_name" -o pid= | xargs)
        if [ -n "$pids" ]; then
            # Get the process path for the main thread
            IFS=" " read -ra process_info <<< "$(get_process_info "$(echo "$pids" | head -n 1)")"
            process_path="${process_info[1]}"
            echo "Process with name '$process_name' (PID: $pids) is running:"
            echo "Path: $process_path"

            prompt_kill_signal
            if [ "$kill_signal" == "y" ]; then
                echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
                read -r wait_time
                if [ -z "$wait_time" ]; then
                    wait_time=5
                fi
                handle_process_termination "$pids" 15 "$wait_time"
            elif [ "$kill_signal" == "k" ]; then
                handle_process_termination "$pids" 9 2
            fi
        else
            # Find near matches for the process name
            near_matches=$(find_near_matches "$process_name")
            while true; do
                if [ -n "$near_matches" ]; then
                    echo "No exact match found for '$process_name'. Near matches:"
                    counter=1
                    while read -r match; do
                        echo "$counter) $match"
                        counter=$((counter + 1))
                    done <<< "$near_matches"

                    echo "Enter the number corresponding to the desired process name (or 'q' to quit, 'n' for a new search):"
                    read -r selection
                    if [ "$selection" == "q" ]; then
                        echo "Exiting..."
                        break
                    elif [ "$selection" == "n" ]; then
                        break
                    else
                        selected_process=$(echo "$near_matches" | awk -v sel="$selection" '{if (NR == sel) print $0}')
                        if [ -n "$selected_process" ]; then
                            pids=$(ps -C "$selected_process" -o pid= | xargs)
                            if [ -n "$pids" ]; then
                                IFS=" " read -ra process_info <<< "$(get_process_info "$(echo "$pids" | head -n 1)")"
                                process_path="${process_info[1]}"
                                echo "Process with name '$selected_process' (PID: $pids) is running:"
                                echo "Path: $process_path"

                                prompt_kill_signal
                                if [ "$kill_signal" == "y" ]; then
                                    echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
                                    read -r wait_time
                                    if [ -z "$wait_time" ]; then
                                        wait_time=5
                                    fi
                                    handle_process_termination "$pids" 15 "$wait_time"
                                elif [ "$kill_signal" == "k" ]; then
                                    handle_process_termination "$pids" 9 2
                                fi
                                break
                            else
                                near_matches=$(find_near_matches "$process_name")
                            fi
                        else
                            echo "Invalid selection"
                        fi
                    fi
                else
                    near_matches=$(find_near_matches "$process_name")
                    if [ -n "$near_matches" ]; then
                        continue
                    else
                        echo "Process with name '$process_name' is not running"
                        break
                    fi
                fi
            done
        fi
    fi
fi

done

This allows you to find a running process and kill it using sigterm 15 or sigkill 9 ( hard or soft kills) it has some limited matching ability, so if your not sure what the process is called you can enter part of the name and it will try and match with what it finds, alternatively you can track the process down by listing the top 10 running processes by cpu usage or memory usage, and you can also just view all running proccesses by user.

I just have it as a system command now so when something hangs I hot key a terminal run pidcheck, find it, kill it.

After rereading the OP i realise this doesnt solve for the situation, as sig 9 was tried…

1 Like

While it still didn’t solve the problem since sig 9 was tried, I appreciate your script. I’ll probably use it in the future to terminate stuck processes. Thank you!