(Ponowne publikowanie w unixie zgodnie z sugestią w /programming/13718394/what-should-interactive-shells-do-in-orphaned-process-groups )
Krótkie pytanie brzmi: co powinna zrobić powłoka, jeśli znajduje się w osieroconej grupie procesów, która nie jest właścicielem tty? Ale polecam przeczytać długie pytanie, ponieważ jest zabawne.
Oto zabawny i ekscytujący sposób na przekształcenie laptopa w przenośny ogrzewacz pomieszczeń za pomocą ulubionej powłoki (chyba że jesteś jednym z tych dziwaków z tcsh):
#include <unistd.h>
int main(void) {
if (fork() == 0) {
execl("/bin/bash", "/bin/bash", NULL);
}
return 0;
}
To powoduje, że bash ustala procesor na 100%. Zsh i fish robią to samo, podczas gdy ksh i tcsh mamroczą coś o kontroli zadań, a następnie przewracają się, co jest nieco lepsze, ale niewiele. Aha, i jest to przestępca agnostyczny na platformę: dotyczy to zarówno systemu X, jak i Linux.
My (potencjalnie źle) wyjaśnienie jest następujące: powłoka dziecko wykryje to nie jest na pierwszym planie: tcgetpgrp(0) != getpgrp()
. Dlatego stara się zatrzymać siebie: killpg(getpgrp(), SIGTTIN)
. Ale jego grupa procesów jest osierocona, ponieważ jej rodzic (program C) był liderem i zmarł, a SIGTTIN
wysłany do osieroconej grupy procesów jest po prostu odrzucany (w przeciwnym razie nic nie mogłoby go ponownie uruchomić). Dlatego skorupa potomna nie jest zatrzymywana, ale nadal znajduje się w tle, więc robi to wszystko od razu. Wypłukać i powtórzyć.
Moje pytanie brzmi: w jaki sposób powłoka wiersza poleceń może wykryć ten scenariusz i co należy zrobić? Mam dwa rozwiązania, z których żadne nie jest idealne:
- Spróbuj zasygnalizować proces, którego pid pasuje do naszego identyfikatora grupy. Jeśli to się nie powiedzie
ESRCH
, oznacza to, że prawdopodobnie jesteśmy osieroceni. - Spróbuj nieblokującego odczytu jednego bajtu z
/dev/tty
. Jeśli to się nie powiedzieEIO
, oznacza to, że prawdopodobnie jesteśmy osieroceni.
(Nasz problem ze śledzeniem tego to https://github.com/fish-shell/fish-shell/issues/422 )
Dzięki za twoje przemyślenia!