c-当使用来自timerfd_create的有效fd调用时,为什么timerfd_settime与EBADF一起失败



我有一个创建timerfd计时器的函数,但有时timerfd_settime会返回EBADF(坏文件描述符(。我无法理解timerfd_create返回有效文件描述符的情况,当立即使用timerfd_settime调用时,该描述符会失败。

我将此函数与epoll事件循环一起使用,有时,此函数会返回一个有效的fd,但在添加计时器fd时,epoll_ctl与EBADF一起失败。我想,如果我理解timerfd_settime有时失败的原因,它也会说明epoll失败。

static inline int create_timer(uint32_t interval_ms, uint32_t start_ms)
{
struct itimerspec its = {{0}};
int fd = timerfd_create(CLOCK_MONOTONIC, 0);
if (fd < 0) {
perror("timerfd_create");
return -1;
}
its.it_interval = timespec_ns((int64_t)(interval_ms) * NSEC_PER_MSEC);
if (start_ms)
its.it_value = timespec_ns((int64_t)(start_ms) * NSEC_PER_MSEC);
else
its.it_value.tv_nsec = 1;
if (timerfd_settime(fd, 0, &its, NULL) < 0) {
perror("timerfd_settime");
close(fd);
return -1;
}
return fd;
}

它用于多线程";curl_multi_socket";应用有多个工作线程,每个工作线程通常需要下载许多文件并对其进行解析。每个线程都有自己的epoll循环。线程间通信是通过使用unix套接字来处理的。

该函数用于设置CURLs timerfunc回调的超时:

static int fetch_timerfunc(CURLM *curlm, long timeout_ms, void *ctx)
{
struct fetch *cm = (struct fetch*) ctx;
struct epoll_event ev = {};
// Cancel previous timeout, if any
if (cm->timer_fd > 0) {
close(cm->timer_fd);
cm->timer_fd = 0;
}
if (timeout_ms < 0) {
return 0;
}
cm->timer_fd = create_timer(0, timeout_ms);
if (cm->timer_fd < 0) {
perror("fetch_timerfunc: create_timer");
return cm->timer_fd;
}
ev.events = EPOLLIN;
ev.data.fd = CURL_SOCKET_TIMEOUT;
if (epoll_ctl(cm->epoll_fd, EPOLL_CTL_ADD, cm->timer_fd, &ev) < 0) {
if (!exiting) {
perror("fetch_timerfunc: epoll_ctl");
}
}
return 0;
}

@KamilCuk是对的。另一个地方的错误导致一个线程有时会连续多次快速关闭fd 0。这意味着timerfd_create有时会返回0作为其分配的fd,并且在调用timerfd_settime之前,它会在有缺陷的线程中立即关闭。

最新更新