Что такое сигнал SIGCHLD в Linux?

Ответ

SIGCHLD — это сигнал, который ядро Linux отправляет родительскому процессу при изменении состояния его дочернего процесса (завершение, остановка SIGSTOP или возобновление SIGCONT).

Зачем это нужно в DevOps/администрировании? Основная задача — предотвратить появление "зомби"-процессов (процессов, завершивших работу, но все еще занимающих запись в таблице процессов). Родительский процесс должен вызвать системный вызов wait() (или его варианты), чтобы получить статус завершения дочернего процесса и освободить ресурсы.

Практический пример в скрипте:

#!/bin/bash
# Устанавливаем обработчик для SIGCHLD
cleanup() {
    echo "[$(date)] Дочерний процесс завершился. Выполняем wait."
    wait -n  # Ждем завершения любого дочернего процесса
}
trap cleanup SIGCHLD

# Запускаем несколько фоновых процессов
sleep 30 &
P1=$!
sleep 60 &
P2=$!

echo "Родительский процесс PID $$ запущен. Дочерние: $P1, $P2"
# Родительский процесс может продолжать свою работу
while true; do
    echo "Родительский процесс работает..."
    sleep 10
done

Ключевые моменты для DevOps:

  • Демоны и супервизоры (systemd, supervisord) активно используют этот механизм для управления своими дочерними службами.
  • Игнорирование SIGCHLD или отсутствие вызова wait() может привести к утечке ресурсов (PID).
  • В контейнерах (Docker) процесс с PID 1 должен корректно обрабатывать SIGCHLD, чтобы перехватывать сигналы от своих дочерних процессов.

Ответ 18+ 🔞

А, слушай, вот тебе история про одного незаметного, но охуенно важного пацана в мире процессов — SIGCHLD. Представь: твой дочерний процесс на Linux, типа, закончил свои дела — отработал, сдох, остановился или, наоборот, очухался. Так вот ядро, такое заботливое, сразу шлёт родителю сигнал: «Эй, чувак, у тебя там ребёнок состояние поменял!». Это и есть SIGCHLD, ёпта.

А нахуя это вообще нужно нам, админам и девопсам? Вот смотри, главная фишка — не допустить появления зомби. Нет, не тех, что за мозгом, а процессов, которые уже кончились, но в системной таблице торчат как бельмо на глазу, записи занимают. Родитель обязан сделать wait() (или его братьев), чтобы статус завершения забрать и ресурсы освободить. Иначе — мусор, утечка PID, в общем, пиздец, Карл.

Чисто практика, на баше:

#!/bin/bash
# Вешаем обработчик на SIGCHLD
cleanup() {
    echo "[$(date)] Дочерний процесс завершился. Выполняем wait."
    wait -n  # Ждём любого дочернего
}
trap cleanup SIGCHLD

# Запускаем фоновые процессы, как будто они просто поспать легли
sleep 30 &
P1=$!
sleep 60 &
P2=$!

echo "Родительский процесс PID $$ запущен. Дочерние: $P1, $P2"
# Родитель может дальше свою работу делать, не заморачиваясь
while true; do
    echo "Родительский процесс работает..."
    sleep 10
done

Что тут важно для нашей братии, которая с серваками возится:

  • Все эти ваши демоны и супервизоры (systemd, supervisord) — они на этом механизме просто помешаны. Без него управлять службами — это как пытаться собрать рассыпанную соль голыми руками, доверия ебать ноль.
  • Если забить хуй на SIGCHLD и не вызывать wait() — готовься к утечке PID. Это как оставлять после себя пустые бутылки на чужой даче — рано или поздно хозяин приедет и ебёт тебя в сраку.
  • Особенно трепетно к этому относятся в контейнерах (Docker). Там процесс с PID 1 — он как главный по тарелкам, обязан SIGCHLD обрабатывать правильно, чтобы сигналы от детей ловить. Иначе весь этот ваш красивый оркестр из микросервисов накроется медным тазом.