2013-06-06 32 views
6

Tôi có sau chức năng sigaction handlerLàm thế nào để tạo một hàm async-signal-safe?

void signal_term_handler(int sig) 
{ 
    printf("EXIT :TERM signal Received!\n"); 
    int rc = flock(pid_file, LOCK_UN | LOCK_NB); 
    if(rc) { 
     char *piderr = "PID file unlock failed!"; 
     fprintf(stderr, "%s\n", piderr); 
     printf(piderr); 
    } 
    abort(); 
} 

Có người nói với tôi rằng flockprintf không async-tín hiệu an toàn. Và tôi không thể tìm thấy chức năng an toàn không đồng bộ-tín hiệu thay thế cho flock trong số list này.

và theo liên kết ở trên:

khi một tín hiệu ngắt một chức năng không an toàn và các tín hiệu bắt chức năng gọi một chức năng không an toàn, hành vi là undefined

Có một cách thế nào để thực hiện flock async-signal-safe? Hoặc có giải pháp khác để thực hiện flock khi tôi nhận được tín hiệu TERM không?

+0

Bản sao có thể có của [Cách tránh sử dụng printf trong trình xử lý tín hiệu?] (Https://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler) cho 'printf', https://stackoverflow.com/questions/16979059/use-flock-in-the-sigaction-handler cho' flock'. –

Trả lời

4

Bạn có thể sử dụng fcntl() làm phương án thay thế cho đàn.

+0

Hãy nhận biết rằng ngữ nghĩa của 'fcntl()' khóa khác và hữu ích hơn so với 'flock()'. – jilles

+0

Trong thực tế, tôi có thể sử dụng fcntl để phát triển một thuộc tính mới flock() chức năng như được chỉ ra trong [topic] này (http://stackoverflow.com/questions/16988256/how-to-lock-and-unlock-pid-file- với-fcntl). Cảm ơn bạn đã cho câu trả lời – MOHAMED

0

Bạn có thể sử dụng exit() thay vì abort() trong trình xử lý tín hiệu và sau đó đặt các chức năng không an toàn của bạn vào trình xử lý thoát bằng cách sử dụng atexit().

Cập nhật: Nói chung, bạn không nên đặt bất kỳ lệnh gọi hệ thống nào có khả năng chặn trong trình xử lý tín hiệu của mình. Một cách để tránh điều này là chỉ cần đặt một lá cờ trong trình xử lý tín hiệu của bạn, và sau đó thực hiện các chức năng bạn muốn trong ngữ cảnh của vòng lặp chính của bạn.

volatile int shutdown = 0; 

void signal_term_handler(int sig) 
{ 
    shutdown = 1; 
} 

void cleanup() { 
    printf("EXIT :TERM signal Received!\n"); 
    int rc = flock(pid_file, LOCK_UN | LOCK_NB); 
    if(rc) { 
     char *piderr = "PID file unlock failed!"; 
     fprintf(stderr, "%s\n", piderr); 
     printf(piderr); 
    } 
} 

void *workerFunction(void *arg) { 
    while (!shutdown) { 
     ... do stuff ... 
    } 
    return NULL; 
} 

int main(int argc, char *argv[]) { 
    //... 
    pthread_create(...,workerFunction,...); 
    pthread_join(...); 
    cleanup(); 
    return 0; 
} 
+0

Thoát-xử lý có thể được gọi là đồng bộ. Làm như vậy từ một trình xử lý tín hiệu gọi không đồng bộ làm cho chúng chạy như thế nào? – alk

+0

Phải, tôi đã không đọc đủ câu hỏi một cách cẩn thận. Tôi đoán tôi đã trả lời một câu hỏi cơ bản hơn về cách tránh các chức năng không an toàn trong trình xử lý tín hiệu. Trong trường hợp này, bạn sẽ muốn thay thế exit() bằng một cái gì đó như thiết lập một cờ tắt máy. –

+0

điều này là sai; nó phải là biến động sig_atomic_t –

4

flock() thường không đồng bộ-tín hiệu an toàn vì đó là cuộc gọi hệ thống. Ngữ nghĩa của nó làm cho nó khó khăn để thực hiện nó một cách khác nhau. Nó không nằm trong danh sách các chức năng an toàn không đồng bộ của POSIX vì nó không có trong POSIX.

Bạn có thể không cần mở khóa rõ ràng vì các khóa flock() được tự động phát hành khi tất cả các mô tả tệp đề cập đến mô tả tệp đang mở sẽ bị đóng.

Các cuộc gọi printf()fprintf() phải được thay thế bằng các cuộc gọi thích hợp write(). Các chức năng stdio không nằm trong danh sách các chức năng an toàn-tín hiệu không đồng bộ và thường mạnh mẽ không đồng bộ-tín hiệu-không an toàn.

Cuộc gọi abort() có lẽ được thay thế tốt nhất bằng cách đặt tín hiệu thành hành động mặc định và gửi lại cho chính bản thân; theo cách này, các shell biết rằng chương trình của bạn đã thoát do tín hiệu và có thể hủy bỏ các chuỗi lệnh khi thích hợp.

+0

Tôi có thể sử dụng 'flock()' mà không có vấn đề trong xử lý sigaction? – MOHAMED

+0

Có, nhưng như tôi đã nói bạn có thể không cần. – jilles

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