Understanding SIGHUP Behavior: Why Background Processes Survive Shell Logoff in Linux Systems


2 views

During routine system administration tasks, many Linux users encounter an interesting behavior: background processes launched from an interactive shell continue running even after the user logs off. This contradicts common expectations that all child processes should receive SIGHUP when their controlling terminal closes.

# Example demonstrating the behavior
$ cat /dev/zero > /dev/null &
[1] 12345
$ exit
# After relogin:
$ ps -p 12345
  PID TTY          TIME CMD
12345 ?        00:00:12 cat

The key factor determining SIGHUP behavior lies in how the shell handles process groups and session leaders. Modern shells like bash implement sophisticated job control that affects signal propagation:

  • Processes launched with & are created in separate process groups
  • The shell sets these processes to ignore SIGHUP by default
  • Upon logout, only the session leader (the shell itself) receives SIGHUP

The behavior stems from POSIX terminal management specifications. When examining the process hierarchy:

$ ps -o pid,ppid,pgid,sid,comm
  PID  PPID  PGID   SID COMMAND
 1234  1233  1234  1234 bash
12345  1234 12345  1234 cat

We observe that while the background process shares the same session ID (SID) as the shell, it resides in a different process group (PGID). This isolation prevents automatic SIGHUP propagation.

For predictable behavior across systems, consider these alternatives:

# Method 1: Explicitly trap SIGHUP
$ (trap '' HUP; my_command &)

# Method 2: Use disown after launching
$ my_command &
$ disown

# Method 3: Create a new session
$ setsid my_command

This behavior has important consequences for:

  • Long-running data processing jobs
  • Server maintenance scripts
  • Automated backup operations

Understanding these mechanics helps system administrators design more reliable process management strategies and avoid unexpected process termination or persistence.


During routine server maintenance, I noticed something peculiar about background processes in Linux. When launching a process in the background (either with & or via CTRL-Z + bg) and then logging out, the process continues running and gets reparented to init (PID 1) without receiving any signals.


# Test case 1: Simple background process
$ cat /dev/zero > /dev/null &
[1] 12345
$ exit

To verify this behavior, I conducted tests across different scenarios:

  • Physical console vs SSH sessions
  • Different process types (SCP, cat, custom scripts)
  • Multiple Linux distributions (CentOS 5.4, VMware ESX 3.5)

# Monitoring process signals with strace
$ strace -p 12345 -e trace=signal

Contrary to common belief, the shell's behavior differs based on:

  • Interactive vs non-interactive shells
  • Job control settings (set -m)
  • Terminal ownership (setsid vs regular processes)

# Creating a process that ignores SIGHUP
#include <signal.h>
#include <unistd.h>

int main() {
    signal(SIGHUP, SIG_IGN);
    while(1) sleep(1);
    return 0;
}

Newer init systems like systemd handle orphaned processes differently:


# Checking process hierarchy
$ pstree -s -p 12345
systemd(1)───myprocess(12345)

For reliable process management, consider these alternatives:


# Proper daemonization techniques
nohup command &>/dev/null &
disown -h %1

# Using screen/tmux for long-running processes
tmux new -s mysession
command
Ctrl-b d

The Linux kernel's process handling involves:

  • Process group leadership
  • Session management
  • Terminal control

# Creating a new session
setsid command

For production systems, recommended approaches include:


# Systemd service unit example
[Unit]
Description=My Daemon Service

[Service]
ExecStart=/usr/local/bin/mydaemon
Restart=always
User=daemon

[Install]
WantedBy=multi-user.target