Vỏ tương tác nên làm gì trong các nhóm quá trình mồ côi?


10

(Đăng lại trong unix theo đề xuất trong /programming/13718394/what-should-interactive-shells-do-in-orphaned- Process-groups )

Câu hỏi ngắn gọn là, một cái vỏ nên làm gì nếu nó nằm trong nhóm quy trình mồ côi không sở hữu tty? Nhưng tôi khuyên bạn nên đọc câu hỏi dài bởi vì nó thú vị.

Đây là một cách thú vị và thú vị để biến máy tính xách tay của bạn thành một máy sưởi không gian di động, sử dụng lớp vỏ yêu thích của bạn (trừ khi bạn là một trong những người lạ đó):

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

Điều này gây ra bash để chốt CPU ở mức 100%. zsh và cá cũng làm như vậy, trong khi ksh và tcsh lẩm bẩm điều gì đó về kiểm soát công việc và sau đó keel qua, điều này tốt hơn một chút, nhưng không nhiều. Ồ, và đó là một kẻ phạm tội bất khả tri về nền tảng: OS X và Linux đều bị ảnh hưởng.

Giải thích (có khả năng sai) của tôi là như sau: shell con phát hiện nó không nằm ở phía trước : tcgetpgrp(0) != getpgrp(). Vì vậy, nó cố gắng để ngăn chặn chính nó : killpg(getpgrp(), SIGTTIN). Nhưng nhóm quy trình của nó là mồ côi, bởi vì cha mẹ của nó (chương trình C) là người lãnh đạo và đã chết, và SIGTTINđược gửi đến một nhóm quy trình mồ côi bị bỏ rơi (nếu không thì không thể bắt đầu lại được). Do đó, lớp vỏ con không dừng lại, nhưng nó vẫn ở trong nền, vì vậy nó sẽ làm lại tất cả ngay lập tức. Rửa sạch và lặp lại.

Câu hỏi của tôi là, làm thế nào một shell dòng lệnh có thể phát hiện ra kịch bản này, và điều gì là đúng cho nó để làm gì? Tôi có hai giải pháp, cả hai đều không lý tưởng:

  1. Cố gắng báo hiệu quá trình có pid khớp với ID nhóm của chúng tôi. Nếu thất bại ESRCH, điều đó có nghĩa là chúng ta có thể mồ côi.
  2. Hãy thử đọc không chặn một byte từ /dev/tty. Nếu thất bại EIO, điều đó có nghĩa là chúng ta có thể mồ côi.

(Vấn đề của chúng tôi theo dõi vấn đề này là https://github.com/fish-shell/fish-shell/issues/422 )

Cảm ơn những suy nghĩ của bạn!

Câu trả lời:


4

Tôi đồng ý với phân tích của bạn và tôi đồng ý rằng có vẻ như bạn phải phát hiện xem nhóm quy trình của bạn có mồ côi hay không.

tcsetattrcũng có nghĩa là quay trở lại EIOnếu nhóm quy trình mồ côi (và chúng tôi không chặn / bỏ qua SIGTT OU . Đó có thể là một cách ít xâm phạm hơn so với readthiết bị đầu cuối.

Lưu ý rằng bạn có thể sao chép nó bằng:

(bash<&1 &)

Bạn cần chuyển hướng nếu không stdin được chuyển hướng đến / dev / null khi chạy lệnh trong nền.

(bash<&1 & sleep 2)

Cung cấp cho hành vi thậm chí kỳ lạ hơn, bởi vì bạn kết thúc với hai vỏ đọc từ thiết bị đầu cuối. Họ đang phớt lờ SIGTTINvà cái mới không phát hiện ra, một khi nó bắt đầu thì nó không còn nằm trong nhóm quy trình tiền cảnh.

ksh93Giải pháp của nó không quá tệ: chỉ đi tối đa 20 lần (thay vì vô hạn) qua vòng lặp đó trước khi từ bỏ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.