[英]getifaddrs returning 'bad file descriptor'/crashing the application
在我的程序中,我有一個線程必須持續監視網絡接口,因此它在 while 循環中不斷使用 getifaddrs()。
while(true) {
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs couldn't fetch required data");
exit(EXIT_FAILURE);
}
//Iterate through interfaces linked list
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
//monitoring logic
}
//Free linked list
freeifaddrs(ifaddr);
//Sleep for specified time fo next polling cycle
usleep(1000);
}
大多數時候我的程序運行良好。 但是,有時 getifaddrs() 返回 -1 和 errNo = EBADF(bad file descriptor) 。 為了不退出我的線程,我暫時用 continue 替換了 exit(因為我不希望我的程序因此而結束)。 但是,我很想知道在哪些情況下 getifaddrs() 會返回“錯誤文件描述符”錯誤,以及我是否可以采取一些措施避免這種情況發生?
編輯
用“繼續”替換“退出”並沒有解決我的問題。 有時調用 getifaddrs() 會使應用程序崩潰!
下面給出的是使用生成的核心文件從 gdb 獲得的回溯。
Program terminated with signal 6, Aborted.
#0 0x00007fe2df1ef387 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-37.el7_6.x86_64 libcom_err-1.42.9-16.el7.x86_64 libgcc-4.8.5-39.el7.x86_64 libselinux-2.5-14.1.el7.x86_64 libstdc++-4.8.5-39.el7.x86_64 openssl-libs-1.0.2k-19.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-18.el7.x86_64
(gdb) bt
#0 0x00007fe2df1ef387 in raise () from /lib64/libc.so.6
#1 0x00007fe2df1f0a78 in abort () from /lib64/libc.so.6
#2 0x00007fe2df231ed7 in __libc_message () from /lib64/libc.so.6
#3 0x00007fe2df231fbe in __libc_fatal () from /lib64/libc.so.6
#4 0x00007fe2df2df4c2 in __netlink_assert_response () from /lib64/libc.so.6
#5 0x00007fe2df2dc412 in __netlink_request () from /lib64/libc.so.6
#6 0x00007fe2df2dc5ef in getifaddrs_internal () from /lib64/libc.so.6
#7 0x00007fe2df2dd310 in getifaddrs () from /lib64/libc.so.6
#8 0x000000000047c03c in __interceptor_getifaddrs.part.0 ()
操作系統:Red Hat Enterprise Linux 服務器版本 7.8(邁坡)
GLIBC 版本:2.17
根據man7.org getifaddrs ,任何套接字操作都可能是EBADF
的原因
錯誤
getifaddrs() 可能會失敗並為 socket(2)、bind(2)、getsockname(2)、recvmsg(2)、sendto(2)、malloc(3) 或 realloc(3) 指定的任何錯誤設置 errno .
不相關,但你在某處做freeifaddrs()
嗎?
手冊頁中的以下示例已修改為包含您的忙循環和usleep
在 valgrind 下運行了幾分鍾而沒有拋出錯誤; 盡管我的服務器在運行此示例時沒有任何網絡接口出現故障或上線。
我在具有glibc-2.17-323.el7_9.x86_64
的 CentOS 7.9 上進行了測試。
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct ifaddrs *ifaddr, *ifa;
int family, s;
char host[NI_MAXHOST];
while (1) {
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}
/* Walk through linked list, maintaining head pointer so we
can free list later */
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
/* Display interface name and family (including symbolic
form of the latter for the common families) */
// Commented out
}
freeifaddrs(ifaddr);
usleep(1000);
}
exit(EXIT_SUCCESS);
}
有趣的是:GNU 的 glibc-2.17 沒有斷言__netlink_assert_response
,但 GNU 的 glibc-2.31 有。 所以,這是 RedHat 稍后修補的東西(您可以使用重新訪問我的步驟):
SRC=`basename $(rpm -q glibc) .x86_64`.src.rpm
wget --no-check-certificate http://vault.centos.org/7.9.2009/updates/Source/SPackages/${SRC}
CPIO=`basename ${SRC} .rpm`.cpio
rpm2cpio ${SRC} > ${CPIO}
mkdir glibc-src && cd glibc-src
cpio -ivd < ${CPIO}
這表明,在您的情況下失敗的斷言是由 Patch glibc-rh1443872.patch
添加的,其中指出:
提交 2eecc8afd02d8c65cf098cbae4de87f332dc21bd
作者: ...
日期:2015 年 11 月 9 日星期一 12:48:41 +0100
終止來自 kernel 的無效網絡鏈接響應的進程 [BZ #12926]
Bugzilla 條目https://sourceware.org/bugzilla/show_bug.cgi?id=12926提供了有關 NetLink 接口有損的詳細信息。
現在所有這些都不能回答你的問題:為什么getifaddrs
失敗並且 glibc 用信號SIGABRT
殺死你的進程。
就像 [@matthieu] 一樣,假設您沒有在監控邏輯中弄亂您的堆棧和/或指針ifaddr
,這仍然可能是 kernel 和 glibc 之間的通信錯誤,需要進一步調查。 作為一種解決方法,您可能會暫時捕獲中止信號,如如何處理 SIGABRT 信號中所述?
https://patchwork.ozlabs.org/project/netdev/patch/5638B93F.3090202@redhat.com/
在鏈接中它說崩潰的原因是。 “netlink sockets 的 recvmsg 系統調用在文件描述符競爭后特別容易拾取不相關的數據(由於其他地方的文件描述符管理問題,描述符在多線程進程中同時關閉和重新打開)。 ”。
所以我認為你要么不使用單獨的線程,要么在netlink函數周圍使用一些鎖定機制。
當您在主線程中監視網絡接口時,至少只需確認它是否仍然崩潰。
幸運的是,我已經能夠追蹤問題背后的根本原因。 該方案已在此處詳細說明。
所以基本上,我程序中的一個線程有這個“雙重關閉”錯誤,有時會導致問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.