ZLMediaKit / ZLToolKit

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

Windows下使用,创建TcpServer时抛出了异常"addEvent | select() can not watch fd bigger than 1024" #228

Closed Hecravi-Sali closed 1 month ago

Hecravi-Sali commented 2 months ago

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 之前代码是正常工作的。

谢谢

wasphin commented 2 months ago

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

#ifndef _WIN32
        if (fd >= FD_SETSIZE) {
            WarnL << "select() can not watch fd bigger than " << FD_SETSIZE;
            return -1;
        }
#endif
Hecravi-Sali commented 2 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
    }

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