ZLMediaKit / ZLToolKit

一个基于C++11的轻量级网络框架,基于线程池技术可以实现大并发网络IO
MIT License
1.98k stars 588 forks source link

When using Windows, an exception "addEvent | select() can not watch fd bigger than 1024" was thrown when creating a TcpServer. #228

Closed Hecravi-Sali closed 6 months ago

Hecravi-Sali commented 6 months ago

git commit: 26d54bbc7b1860a450434dce49bbc8fcbcbae88b

Log: 2024-05-16 11:28:29.071 W [tstj.exe] [15636-12384] EventPoller.cpp:144 addEvent | select() can not watch fd bigger than 1024 When starting, using a singleton, an exception was thrown when building a TcpServer in the constructor

ServerManager() {
    serverPtr = std::make_shared<toolkit::TcpServer>();
    ....
}

The exception was located in the EventPoller.cpp file

#else
        if (fd >= FD_SETSIZE) {
            WarnL << "select() can not watch fd bigger than " << FD_SETSIZE;
            return -1;
        }
        auto record = std::make_shared<Poll_Record>();
        record->fd = fd;
        record->event = event;
        record->call_back = std::move(cb);
        _event_map.emplace(fd, record);
        return 0;
#endif

How to solve this situation? The code was working normally before git commit: 43004bef30cb4b48a7f8238027cee1054733f5b1.

Thank you

git commit: 26d54bbc7b1860a450434dce49bbc8fcbcbae88b

日志记录: 2024-05-16 11:28:29.071 W [tstj.exe] [15636-12384] EventPoller.cpp:144 addEvent | select() can not watch fd bigger than 1024 启动时,使用单例,在构造函数中构建了一个TcpServer

ServerManager() {
    serverPtr = std::make_shared<toolkit::TcpServer>();
    ....
}

时抛出异常,定位到EventPoller.cpp文件里

#else
        if (fd >= FD_SETSIZE) {
            WarnL << "select() can not watch fd bigger than " << FD_SETSIZE;
            return -1;
        }
        auto record = std::make_shared<Poll_Record>();
        record->fd = fd;
        record->event = event;
        record->call_back = std::move(cb);
        _event_map.emplace(fd, record);
        return 0;
#endif

这种情况该如何解决呢?在 git commit: 43004bef30cb4b48a7f8238027cee1054733f5b1 之前代码是正常工作的。

谢谢

TRANS_BY_GITHUB_AI_ASSISTANT

wasphin commented 6 months ago

It seems like the change accidentally deleted the condition for judging Windows. Should we try adding it back manually?

#ifndef _WIN32
        if (fd >= FD_SETSIZE) {
            WarnL << "select() can not watch fd bigger than " << FD_SETSIZE;
            return -1;
        }
#endif

看改动确实向误删了判断 windows 的条件,手动加回来试试?

#ifndef _WIN32
if (fd >= FD_SETSIZE) {
WarnL << "select() can not watch fd bigger than " << FD_SETSIZE;
return -1;
}
#endif

TRANS_BY_GITHUB_AI_ASSISTANT

Hecravi-Sali commented 6 months ago
    if (isCurrentThread()) {
#if defined(HAS_EPOLL)
        struct epoll_event ev = {0};
        ev.events = (toEpoll(event)) | EPOLLEXCLUSIVE;
        ev.data.fd = fd;
        int ret = epoll_ctl(_event_fd, EPOLL_CTL_ADD, fd, &ev);
        if (ret != -1) {
            _event_map.emplace(fd, std::make_shared<PollEventCB>(std::move(cb)));
        }
        return ret;
#elif defined(HAS_KQUEUE)
        struct kevent kev[2];
        int index = 0;
        if (event & Event_Read) {
            EV_SET(&kev[index++], fd, EVFILT_READ, EV_ADD, 0, 0, nullptr);
        }
        if (event & Event_Write) {
            EV_SET(&kev[index++], fd, EVFILT_WRITE, EV_ADD, 0, 0, nullptr);
        }
        int ret = kevent(_event_fd, kev, index, nullptr, 0, nullptr);
        if (ret != -1) {
            _event_map.emplace(fd, std::make_shared<PollEventCB>(std::move(cb)));
        }
        return ret;
#else 
#ifndef _WIN32
        //win32平台,socket套接字不等于文件描述符,所以可能不适用这个限制
        if (fd >= FD_SETSIZE || _event_map.size() >= FD_SETSIZE) {
            WarnL << "select() can not watch fd bigger than " << FD_SETSIZE;
            return -1;
        }
#endif

        auto record = std::make_shared<Poll_Record>();
        record->fd = fd;
        record->event = event;
        record->call_back = std::move(cb);
        _event_map.emplace(fd, record);
        return 0;
#endif
    }

The Windows platform judgment condition in addevent has been added back. Testing shows no problems, and it can be used normally.


if (isCurrentThread()) {
#if defined(HAS_EPOLL)
struct epoll_event ev = {0};
ev.events = (toEpoll(event)) | EPOLLEXCLUSIVE;
ev.data.fd = fd;
int ret = epoll_ctl(_event_fd, EPOLL_CTL_ADD, fd, &ev);
if (ret != -1) {
_event_map.emplace(fd, std::make_shared<PollEventCB>(std::move(cb)));
}
return ret;
#elif defined(HAS_KQUEUE)
struct kevent kev[2];
int index = 0;
if (event & Event_Read) {
EV_SET(&kev[index++], fd, EVFILT_READ, EV_ADD, 0, 0, nullptr);
}
if (event & Event_Write) {
EV_SET(&kev[index++], fd, EVFILT_WRITE, EV_ADD, 0, 0, nullptr);
}
int ret = kevent(_event_fd, kev, index, nullptr, 0, nullptr);
if (ret != -1) {
_event_map.emplace(fd, std::make_shared<PollEventCB>(std::move(cb)));
}
return ret;
#else 
#ifndef _WIN32
//win32平台,socket套接字不等于文件描述符,所以可能不适用这个限制
if (fd >= FD_SETSIZE || _event_map.size() >= FD_SETSIZE) {
WarnL << "select() can not watch fd bigger than " << FD_SETSIZE;
return -1;
}
#endif
    auto record = std::make_shared<Poll_Record>();
    record->fd = fd;
    record->event = event;
    record->call_back = std::move(cb);
    _event_map.emplace(fd, record);
    return 0;

endif

}

将addevent中windows平台判断条件添加回来了,测试看来没有问题,可以正常使用了

`TRANS_BY_GITHUB_AI_ASSISTANT`