Commit b74ed513 authored by jan.koester's avatar jan.koester
Browse files

test

parent e0d2f990
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -350,7 +350,8 @@ namespace netplus {

            // Cache fd early; after close it may be invalid / reused
            int fd = -1;
            if (ccon->csock) fd = ccon->csock->fd();
            if (ccon->csock)
                fd = ccon->csock->fd();

            // 1) Remove from epoll (ignore ENOENT / EBADF)
            if (fd >= 0) {
+20 −41
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ namespace netplus {
    std::mutex POLL_HANDLER_MUTEX;

    std::vector<socket*> SSOCKETS;
    std::map<int,con*>    CONNECTIONS;
    std::map<int,std::shared_ptr<con>>    CONNECTIONS;

    class pollapi {
    public:
@@ -357,59 +357,38 @@ namespace netplus {
        }

        void CloseEventHandler(int pos, const int tid, ULONG_PTR args) {
            con* ccon = reinterpret_cast<con*>(_Events[pos].udata);
            if (!ccon) return;

            // Lock connection first (so nobody is inside Read/Write handler),
            // then take global map lock later.
            std::unique_lock<std::mutex> conn_lock(ccon->event_mutex);
            con* raw_ptr = reinterpret_cast<con*>(_Events[pos].udata);
            if (!raw_ptr) return;

            // Cache fd early; after close it may be invalid.
            int fd = -1;
            if (ccon->csock) fd = ccon->csock->fd();
            std::shared_ptr<con> ccon;

            // 1) Remove from kqueue (ignore ENOENT)
            {
                std::lock_guard<std::mutex> global_lock(POLL_HANDLER_MUTEX);
                int fd = (raw_ptr->csock) ? raw_ptr->csock->fd() : -1;
                if (fd >= 0) {
                struct kevent kev[2];
                EV_SET(&kev[0], fd, EVFILT_READ,  EV_DELETE, 0, 0, nullptr);
                EV_SET(&kev[1], fd, EVFILT_WRITE, EV_DELETE, 0, 0, nullptr);

                // kevent can return -1 even if one filter didn't exist; treat ENOENT as OK.
                if (kevent(_pollFD, kev, 2, nullptr, 0, nullptr) < 0) {
                    if (errno != ENOENT) {
                        NetException except;
                        char errstr[255];
                        strerror_r_netplus(errno, errstr, 255);
                        except[NetException::Error] << "CloseEventHandler: failed to remove fd from kqueue: " << errstr;
                        // continue cleanup anyway
                    auto it = CONNECTIONS.find(fd);
                    if (it != CONNECTIONS.end()) {
                        ccon = it->second;
                        CONNECTIONS.erase(it);
                    }
                }
            }

            // 2) Inform application layer (do this before freeing/closing state)
            if (!ccon) return;

            std::unique_lock<std::mutex> conn_lock(ccon->event_mutex);

            try {
                evconnection->DisconnectEvent(*ccon, tid, args);
            } catch (...) {
                // don't let DisconnectEvent prevent cleanup
            }
            } catch (...) {}

            // 3) Close socket
            if (ccon->csock) {
                try { ccon->csock->close(); } catch (...) {}
            }

            // 4) Remove from global map (use cached fd; csock may be gone)
            {
                std::lock_guard<std::mutex> global_lock(POLL_HANDLER_MUTEX);
                if (fd >= 0) CONNECTIONS.erase(fd);
                try {
                    ccon->csock->close();
                } catch (...) {}
            }

            // 5) Clear event slot udata so it can’t be reused accidentally
            _Events[pos].udata = nullptr;

            // 6) Destroy connection object
            conn_lock.unlock();
            delete ccon;
        }

    private: