Що повинні робити інтерактивні оболонки в осиротілих процесних групах?


10

(Повторна публікація в unix за пропозицією на /programming/13718394/what-should-interactive-shells-do-in-orphaned-process-groups )

Коротке запитання полягає в тому, що повинна робити оболонка, якщо вона в групі осиротілих процесів, яка не володіє tty? Але рекомендую прочитати довге запитання, бо це забавно.

Ось цікавий та захоплюючий спосіб перетворити ваш ноутбук у портативний обігрівач простору, використовуючи улюблену оболонку (якщо ви не є одним із цих диваків tcsh):

#include <unistd.h>   
int main(void) {
    if (fork() == 0) {
        execl("/bin/bash", "/bin/bash", NULL);
    }
    return 0;
}

Це змушує баш прив’язувати процесор на 100%. zsh і fish роблять те ж саме, тоді як ksh і tcsh нарікають щось на тему контролю над роботою, а потім перебирають кіль, що трохи краще, але не набагато. О, і це злочинець злочинця на платформі: OS X і Linux постраждали.

Мій (потенційно неправильно) пояснення полягає в наступному: дитина оболонка визначає , що вона не на передньому плані: tcgetpgrp(0) != getpgrp(). Тому він намагається зупинити себе: killpg(getpgrp(), SIGTTIN). Але його процесна група осиротіла, тому що її батько (програма С) був лідером і помер, а SIGTTINвідправлений до осиротілої групи процесів просто відкидається (інакше нічого не може запустити його заново). Тому дочірню оболонку не зупиняють, але вона все ще знаходиться на задньому плані, тому це робить все знову, відразу. Промийте і повторіть.

Моє запитання: як оболонка командного рядка може виявити цей сценарій, і що це правильно? У мене є два рішення, жодне з яких не є ідеальним:

  1. Спробуйте подати сигнал, чий pid відповідає нашому ідентифікатору групи. Якщо це не вдається ESRCH, це означає, що ми, ймовірно, сироти.
  2. Спробуйте не блокувати зчитування одного байта від /dev/tty. Якщо це не вдається EIO, це означає, що ми, ймовірно, сироти.

(Наше відстеження цього питання - https://github.com/fish-shell/fish-shell/isissue/422 )

Дякуємо за ваші думки!

Відповіді:


4

Я погоджуюся з вашим аналізом, і я згоден, це здається, що ви повинні виявити, чи є ваша група процесів сиротою чи ні.

tcsetattrтакож покликаний повернутися, EIOякщо група процесів осиротіла (і ми не блокуємо / ігноруємо SIGTT OU . Це може бути менш нав'язливим способом, ніж readна терміналі.

Зауважте, що ви можете відтворити його за допомогою:

(bash<&1 &)

Вам потрібно перенаправлення, інакше stdin буде переспрямовано на / dev / null під час виконання команди у фоновому режимі.

(bash<&1 & sleep 2)

Надає навіть більш дивну поведінку, начебто в кінцевому підсумку з двох оболонок читають з терміналу. Вони ігнорують, SIGTTINі нове не виявляє, як тільки починається, що його вже немає в групі процесу переднього плану.

ksh93Рішення не так вже й погано: пройдіться лише 20 разів (замість нескінченного) через цю петлю, перш ніж відмовлятися.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.