2012-03-03 37 views
5

Mã trong câu hỏi đầu tiên (hạn chế tối đa trường hợp):printf không hoạt động trong xử lý tín hiệu C

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

int counter = 0; 

void react_to_signal(int n) { 
    fprintf(stderr, "Caught!\n"); 
    counter++; 
} 

int main(int argc, char** argv) { 

    signal(SIGINFO, react_to_signal); 

    while (1) { 
     printf("%d\n", counter); 
    } 

    return 0; 
} 

tôi chạy mã này, nó vòng như mong muốn, in ra 0. Sau đó, trong vỏ khác ..

kill -s SIGINFO <pid_of_my_process> 

Tín hiệu được phân phối, c được tăng lên .. nhưng fprintf không xảy ra.

Tại sao lại như vậy? Trong môi trường/bối cảnh nào mã xử lý chạy? Tôi có thể đọc về điều này ở đâu?

+0

Cố gắng làm sạch tiêu bản bằng cách sử dụng 'fflush (stderr)' – Saphrosit

+2

Không sử dụng printf() et.al. bên trong xử lý tín hiệu. Họ không phải là tín hiệu an toàn (ví dụ: có thể gọi malloc(), không an toàn tín hiệu) – wildplasser

+0

Thật thú vị, tôi có thể thề rằng tôi đã thử một biến thể với 'fflush' trước khi tôi đăng. Không bao giờ được biên dịch lại và chạy, hoặc tự bắn vào chân với vòng lặp vô hạn di chuyển màn hình khỏi màn hình. Vì vậy, unromantic và câm. – ntl0ve

Trả lời

14

Nói tóm lại: bạn không thể sử dụng một cách an toàn printf trong xử lý tín hiệu

Có một list of authorized functions trong trang người đàn ông xử lý tín hiệu, trong Async tín hiệu an toàn phần. Không có fprintf trong đó.

Đó là vì chức năng này không phải là reentrant, chủ yếu là vì nó có thể sử dụng malloc và miễn phí. Xem this post để biết giải thích chi tiết.

+0

Được rồi, bây giờ đã rõ. Cảm ơn rất nhiều! – ntl0ve

1

Bạn có thể cần phải fflush stderr để nhận được thông báo viết trước khi chương trình thoát.

+0

Không 'printf' tự động tuôn ra khi nó đạt đến một dòng mới? –

+1

No. Xem https://stackoverflow.com/questions/5229096/does-printf-always-flush-the-buffer-on-encountering-a-newline –

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