2012-01-18 32 views
5

Tôi hiện đang sử dụng tập lệnh để gọi pkill để chấm dứt chương trình C++ của mình. Tuy nhiên tôi nhận thấy rằng các destructors đã không được gọi là từ các dấu vết của tôi khi sử dụng pkill.Cách tốt nhất để thoát khỏi chương trình một cách duyên dáng mà không cần sử dụng pkill

Có cách nào khác để tôi có thể thoát khỏi chương trình một cách duyên dáng không?
pkill dường như không có gì lộn xộn và một số nhật ký trong bộ đệm không được ghi lại. Tôi muốn để có thể tuôn ra trên fstream của tôi và đóng tất cả các nguồn tài nguyên programatically (thay vì dựa vào O/S để làm sạch mess của tôi).

Ứng dụng chạy 24/7 mà không gặp bất kỳ sự cố nào, thời gian duy nhất tôi muốn dừng trong quá trình bảo trì. Ứng dụng không có bất kỳ giao diện người dùng nào cho tôi để nhập thoát.

+0

Loại ứng dụng nào? –

+0

@BasileStarynkevitch, nó là một ứng dụng sản xuất nhận lệnh từ hệ thống khác để thực hiện một số tính toán và giám sát. tôi nên đề cập rằng bất kỳ thay đổi cần phải được kiểm tra đầy đủ trước khi nó đi vào sản xuất. –

+1

Sau đó, nó rất có thể đã có một số vòng lặp sự kiện .... Vì vậy, thêm một ống điều khiển có thể được đơn giản .... Xem thêm trả lời của tôi ... –

Trả lời

4

Bạn làm điều đó bằng cách định nghĩa một handler tín hiệu cho SIGTERM cùng những dòng này:

Một nơi nào đó trong bạn bao gồm khối:

#include <signal.h> 
#include <stdio.h> 

Có , chúng tôi đang làm phong cách C!

Một nơi nào đó ở phần khởi tạo mã của bạn:

signal (SIGTERM, handler); 

và sau đó xác định mã xử lý tín hiệu (tuôn ra tất cả mọi thứ, vv):

void handler(int num) 
{ 
    // we might use this handler for many signals 
    switch (num) 
    { 
    case SIGTERM: 
     // clean up code. 
     break; 
    } 
} 

Bây giờ khi bạn chạy pkill <app>, nơi <app> là tên của tệp thực thi, mã cho handler() sẽ chạy.

Không có thiết bị chuyển mạch, tín hiệu SIGTERM mặc định sẽ được gửi đến ứng dụng. Nếu bạn chọn sử dụng tín hiệu khác, bạn sẽ phải đảm bảo bạn gửi cùng một tín hiệu khi bạn "bắt" trong handler().

Thông tin có liên quan có thể được tìm thấy bởi man 7 signal và tất nhiên, man kill.

+0

Tuy nhiên, tôi sẽ giữ tín hiệu 'SIGTERM' mặc định, được thiết kế để chấm dứt duyên dáng (và cũng là tín hiệu mà trình tự tắt hệ thống sẽ gửi). –

+0

Sau khi phản ánh, tôi đồng ý, 'SIGTERM' có ý nghĩa hơn cho việc này. 'SIGHUP' có lẽ thường được sử dụng để báo hiệu tải lại hoặc tương tự. – zrvan

+0

@BasileStarynkevitch Tôi đã cập nhật câu trả lời. – zrvan

3

Cách tốt nhất là xử lý tín hiệu trong chương trình, sau đó gửi tín hiệu đó bằng kill. Trong trình xử lý tín hiệu, đánh dấu một lá cờ sẽ làm cho vòng lặp chính kết thúc.

4

Trừ khi bạn sửa đổi ứng dụng đích, tôi không thấy cách nào.

xem xét như sau:

int main() 
{ 
    MyClass a; 
    while (true) 
    { 
    } 
} 

Bạn sẽ phải nói với chương trình để thoát khỏi vòng lặp. Nhưng trừ khi bạn có một số cơ chế xử lý tín hiệu trên ứng dụng của mình, điều đó dường như là không thể.

Bạn sẽ cần một cái gì đó như:

int main() 
{ 
    MyClass a; 
    while (!killSignalReceived()) 
    { 
    } 
} 
+1

Tại sao 'while (true && ...)'? –

+0

@LieRyan :)) Trong đầu của tôi, sự thật có thể là bất cứ điều gì, bây giờ tôi thấy nó thừa. –

4

Ngoài Zrvan's answer, lưu ý rằng chỉ một bộ chức năng giới hạn có thể được gọi an toàn từ trình xử lý tín hiệu. Trang người dùng signal(7) và các tiêu chuẩn Posix, yêu cầu chỉ Các chức năng an toàn không đồng bộ hóa tín hiệu có thể được gọi trực tiếp hoặc gián tiếp bên trong trình xử lý tín hiệu.Lưu ý rằng printf hoặc malloc không an toàn trong bộ xử lý tín hiệu. Mã của trình xử lý tín hiệu rất khó để viết (và bạn không thể gỡ lỗi nó một cách dễ dàng, bởi vì gửi tín hiệu không thể tái tạo).

Khi tài liệu Glibc gợi ý, trình xử lý tín hiệu của bạn chỉ có thể đặt biến số volatile sig_atomic_t, vòng lặp chính của bạn sẽ kiểm tra và xử lý.

Bạn cũng có thể quyết định, nếu bạn áp dụng dựa trên sự kiện, một số ổ cắm hoặc ống có tên được dành riêng để kiểm soát nó. Vòng lặp sự kiện đó (có thể sử dụng select(2) hoặc poll(2) hoặc thậm chí pselect hoặc ppoll) có thể xử lý thông báo điều khiển trên đường ống hoặc ổ cắm.

Bạn có thể quan tâm đến các thư viện lặp sự kiện như libevent. Bạn cũng có thể sử dụng thư viện máy chủ HTTP như onion hoặc Wt. Bạn cũng có thể quan tâm đến SNMP hoặc D-bus.

Một thủ thuật để vượt qua giới hạn của trình xử lý tín hiệu là phải viết chúng trên một đường ống cho cùng một quá trình, ví dụ: Qt's doc đang đề xuất. Sau đó, vòng lặp sự kiện sẽ xử lý việc đọc trên đường ống đó.

Nếu ứng dụng của bạn đa luồng, xử lý tín hiệu phức tạp hơn. Một số tín hiệu được gửi tới một chuỗi riêng lẻ.

+0

Đây là nội dung hay, nội dung hay! – zrvan

Các vấn đề liên quan