Що змушує процес Unix вмирати зі зламаною трубою?


30

Ось кілька варіантів, які я придумав, не впевнений, який є правильним.

  1. Сталася помилка зчитування вводу / виводу з труби.
  2. Процес запису на інший кінець труби загинув з відмовою.
  3. Усі процеси, які могли записати на трубу, закрили її.
  4. Буфер запису труби заповнений.
  5. Колектор закрив інший напрямок дуплексної труби.
  6. Написання не вдалося, оскільки не існує процесів, які можна було б прочитати з тексту.
  7. Системний виклик повернув помилку EPIPE, і не було встановлено обробник помилок.

Яке ваше запитання? Ви запитуєте, що з них правильне, чи є якісь інші речі, які можуть спричинити розбиту трубу?
EightBitTony

@EightBitTony Хто з них є правильним
siamii

Відповіді:


38

Процес отримує SIGPIPE, коли він намагається записати на трубу (названу чи ні) або сокет типу SOCK_STREAM, у якого не залишилося жодного зчитувача.

Це взагалі бажана поведінка. Типовий приклад:

find . | head -n 1

Ви не хочете findпродовжувати працювати, коли headвін закінчується (а потім закриває єдиний дескриптор файлів, відкритий для читання в цій трубці).

yesКоманда , як правило , залежить від цього сигналу припинити.

yes | some-command

Буде писати "y", поки деяка команда не припиниться.

Зауважте, що це не лише тоді, коли команди виходять, це коли всі читачі закрили свій читання fd до труби. В:

yes | ( sleep 1; exec <&-; ps -fC yes)
      1 2       1        0

Буде 1 (нижня оболонка), потім 2 (нижня оболонка + сон), потім 1 (нижня оболонка), потім 0 ​​fd зчитування з труби після того, як нижня оболонка явно закриє свій stdin, і ось тоді yesотримає ПІДПИС.

Вище, більшість оболонок використовувати в pipe(2)той час як ksh93використовує socketpair(2), але поведінка таке ж в цьому відношенні.

Коли процес ігнорує SIGPIPE, запис системного виклику ( як правило write, але може бути pwrite, send, splice...) повертається з EPIPEпомилкою. Таким чином, процеси, які хочуть обробити розбиту трубу вручну, зазвичай ігнорують SIGPIPE і вживають заходів при помилці EPIPE.


14

(6)

Написання не вдалося, оскільки не існує процесів, які можна було б прочитати з тексту.

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

Від man 7 pipe:

Якщо всі дескриптори файлів, що відносяться до кінця зчитування труби, були закриті, то запис (2) призведе до формування сигналу SIGPIPE для процесу виклику. Якщо процес виклику ігнорує цей сигнал, то запис (2) не вдається з помилкою EPIPE.

Отже, "зламана труба" - це для письменника те, що EOF - читачеві.


0

Розбита труба трапляється, коли процес читання закінчується перед процесом запису. Тож я б пішов (6)


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