2012-12-04 23 views
0

我正在調試一個選擇循環,通常工作正常,但在重負載下死於分段故障。我發現該程序有時會調用FD_ISSET()來獲取未添加到選擇集的(正確)描述符。就像在下面的代碼片段:FD_ISSET是否可以用未添加到選擇集的描述符調用?

#include <sys/select.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 

void die(const char* msg) 
{ 
    fprintf(stderr, "fatal %s", msg); 
    exit(1); 
} 

int main(void) 
{ 
    FILE* file = fopen("/tmp/test", "r"); 
    if (file == NULL) 
     die("fopen"); 

    int file_fd = fileno(file); 
    fd_set read_fds; 
    int max_fd = 0; 

    FD_ZERO(&read_fds); 
    // Only stdin is added to read_fds. 
    FD_SET(0, &read_fds); 

    if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) < 0) 
     die("select"); 
    if (FD_ISSET(0, &read_fds)) 
     printf("Can read from 0"); 
    // !!! Here FD_ISSET is called with a valid descriptor that was 
    // not added to read_fds. 
    if (FD_ISSET(file_fd, &read_fds)) 
     printf("Can read from file_fd"); 
    return 0; 
} 

很顯然,標有!!!檢查不應該返回true,但它是可能的,它可以是段錯誤的原因是什麼?當我運行的valgrind下這個片段中,沒有錯誤的報道,但是當我在Valgrind的運行我的負載測試我像ocasionnaly seing錯誤:

==25513== Syscall param select(writefds) points to uninitialised byte(s) 
==25513== at 0x435DD2D: ___newselect_nocancel (syscall-template.S:82) 
+0

此代碼不應該SEGFAULT無論'file_fd'是無效的,或者您不在問題發佈的代碼。 – iabdalkader

回答

2

FD_ISSET()進行測試,看是否有文件描述符的一部分集read_fds。這意味着FD_ISSET不應該導致分段錯誤。

嘗試在調用FD_ISSET之前檢查設置的errno值。 select應該導致段錯誤。

另請檢查file_fd的值是否不大於FD_MAX

+1

謝謝。確實FD_ISSET()不是原因。負載測試中的文件描述符數超過了FD_SETSIZE(我的系統上只有1024),這導致select()中斷。我沒有意識到這個限制,我的錯誤印象是select可以處理任意數量的文件描述符(ulimit是唯一的限制)。 –

相關問題