Commit 1548a892 authored by jan.koester's avatar jan.koester
Browse files

test

parent 5deefa3c
Loading
Loading
Loading
Loading
+39 −25
Original line number Diff line number Diff line
@@ -342,43 +342,57 @@ namespace netplus {
        }

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

            if (!_Events[pos].data.ptr) {
                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 *ccon = reinterpret_cast<con*>(_Events[pos].data.ptr);
            // Cache fd early; after close it may be invalid.
            int fd = -1;
            if (ccon->csock) fd = ccon->csock->fd();

            if (!ccon) {
                return;
            }
            std::unique_lock<std::mutex> conn_lock(ccon->event_mutex);
            // 1) Remove from kqueue (ignore ENOENT)
            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);

            if (ccon->csock) {
                try {
                    if (epoll_ctl(_pollFD, EPOLL_CTL_DEL, ccon->csock->fd(), nullptr) < 0) {
                // 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: can't close socket to epoll: " << errstr;
                        throw except;
                        except[NetException::Error] << "CloseEventHandler: failed to remove fd from kqueue: " << errstr;
                        // continue cleanup anyway
                    }
                }
            }

            // 2) Inform application layer (do this before freeing/closing state)
            try {
                evconnection->DisconnectEvent(*ccon, tid, args);
            } catch (...) {
                // don't let DisconnectEvent prevent cleanup
            }

                    ccon->csock->close();

                    CONNECTIONS.erase(ccon->csock->fd());

                } catch (NetException &e) {
                    CONNECTIONS.erase(ccon->csock->fd());
                    conn_lock.unlock();
                    throw e;
            // 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);
            }

            _Events[pos].data.ptr  = nullptr;
            // 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;
        }