Khi một tiến trình Python bị giết trên OS X, tại sao nó không giết các tiến trình con?


7

Tôi thấy mình đã rất bối rối khi quay lại một số thay đổi mà tôi đã tìm thấy khi chuyển các tập lệnh Python từ Linux sang OS X ...

Trên Linux, nếu tập lệnh Python đã gọi os.system () và quá trình gọi bị hủy, quy trình được gọi sẽ bị hủy cùng một lúc.

Tuy nhiên, trên OS X, nếu tiến trình chính bị hủy, mọi thứ mà nó khởi chạy sẽ bị bỏ lại.

Có điều gì đó ở đâu đó trong OS X / Python nơi tôi có thể thay đổi hành vi này không?

Điều này gây ra sự cố trong trang trại kết xuất của chúng tôi, nơi các quy trình có thể bị hủy khỏi GUI quản lý, nhưng quy trình cấp cao nhất thực sự chỉ là một trình bao bọc, vì vậy, trong khi quản lý trang trại kết xuất có thể nghĩ rằng quy trình đã biến mất và máy được giải phóng đối với một nhiệm vụ khác, tác vụ chuyên sâu của bộ xử lý vẫn đang chạy, điều này có thể dẫn đến tắc nghẽn rất lớn.

Tôi biết rằng tôi có thể viết nhiều logic hơn để bắt tín hiệu tiêu diệt và truyền nó cho các tiến trình con, nhưng tôi đã hy vọng rằng nó có thể là thứ gì đó có thể được kích hoạt ở mức thấp hơn.


4
Không có gì cố hữu trong mối quan hệ được thiết lập bởi hệ thống chung (3) sẽ truyền tín hiệu từ một quá trình đến con của nó. Các quy trình mồ côi sẽ được áp dụng bởi init (8) (hoặc launchd (8) trên Mac OS X), nhưng không bị ảnh hưởng trực tiếp bởi mất cha mẹ. Có thể có các mối quan hệ phụ trợ khiến trẻ mồ côi thoát ra, tuy nhiên (ví dụ: nếu có một đường ống giữa cha mẹ và trẻ, trẻ có thể nhận được một EPIPE từ đọc (2) / ghi (2) / v.v. SIGPIPE có thể khiến nó thoát / chết).
Chris Johnsen

2
Có lẽ các nhóm quá trình có liên quan. Nếu quy trình Python là người lãnh đạo nhóm quy trình cho chính nó và con của nó, thì bạn có thể killpg (2) / killpg (3) PID của nó để gửi tín hiệu cho cả nó và con của nó. Làm thế nào, chính xác, bạn đang bắt đầu và giết quá trình Python? Bạn đang sử dụng vỏ? Vỏ nào? Bạn shell thực hiện quá trình Python? Bạn đang sử dụng kill nào? (shell-buildin-kill / kill (1) / kill (2)) Bạn có đang sử dụng bộ lọc âm không? (biểu thị mức sử dụng kiểu killpg) Bạn có đang sử dụng killpg (2) / killpg (3) không?
Chris Johnsen

Tôi thực sự không chắc chắn, thành thật hoàn toàn - đó là một ứng dụng khác đang giết chết. Tôi nghĩ rằng những gì tôi cần làm là bắt tín hiệu tiêu diệt trong kịch bản của mình và đảm bảo rằng nó được truyền cho tất cả các quy trình con. Các quy trình python ban đầu được khởi chạy thông qua tcsh.
Hugh

Chắc chắn, miễn là nó không SIGKILL, bạn có thể bắt nó và đưa nó cho đứa trẻ. Nhưng nếu bạn muốn tách biệt sự khác biệt giữa các nền tảng, bạn cần thu thập thêm thông tin. Bạn nói rằng tcsh(ick) đang bắt đầu quá trình trình bao bọc Python. Nó được thực hiện với exectiền tố lệnh hay chỉ là một lệnh thông thường trong tập lệnh? Về phía kill, bạn có thể sử dụng một cái gì đó như strace(Linux) hoặc ktrace+ kdump(Mac OS X) để tìm hiểu làm thế nào tín hiệu được gửi (kill / killpg? Đối số PID âm?). Những điều này sẽ cung cấp manh mối cho các cuộc điều tra tiếp theo.
Chris Johnsen

Sẽ xem và xem ... Cảm ơn vì lời khuyên!
Hugh

Câu trả lời:


5

Trên Linux, khi bạn giết cha mẹ, đứa trẻ sẽ được gửi SIGHUP , nó thường sẽ giết nó trừ khi nó được dùng để sống như một daemon, trong trường hợp đó, nó sẽ bẫy thở dài. (Tôi nghĩ đây là lý do tại sao người ta thường sử dụng SIGHUP để nói với một daemon để làm mới chính nó, vì nó luôn luôn bị mắc kẹt).

Trên Mac OS XI không thể tìm thấy tài liệu, nhưng có vẻ như không có SIGHUP nào được gửi. Kết quả là quá trình con bị mồ côi, và cha mẹ mới của nó là ông bà.

Cách bạn đối phó với điều này là bạn gửi tín hiệu tiêu diệt đến nhóm quy trình của cha mẹ, chứ không phải chính quy trình cha mẹ. Điều này sẽ nuke tất cả trẻ em và cháu lớn với một cảnh báo. Nếu bất kỳ tiến trình con nào thực hiện setpgrp () hoặc setsid () thì nó sẽ thoát khỏi tư cách thành viên nhóm quy trình. Nó sẽ không nhận được lệnh giết gửi đến nhóm quy trình cũ của nó. Thông thường người ta không cần phải lo lắng về cái sau vì nó thường có chủ ý khi được sử dụng để đạt được mục đích đó.


Điều đó nghe thật tuyệt - tôi sẽ xem và thử xem - cảm ơn
Hugh

Bạn có thể viết một bài kiểm tra vỏ đơn giản chứng minh rằng tín hiệu không được truyền cho trẻ. Đứa trẻ đơn giản sẽ được nhận nuôi bởi init, như đã giải thích ở trên bởi Chris Johnsen. Ngoài ra, thở dài không có nghĩa là để làm mới một deamon, trừ khi deamon được thiết kế đặc biệt để làm như vậy. Hành vi quá trình mặc định là thoát khi nhận được thở dài.
Philippe A.
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.