Loading src/event/epoll.cpp +36 −26 Original line number Diff line number Diff line Loading @@ -342,43 +342,53 @@ namespace netplus { } void CloseEventHandler(int pos, const int tid, ULONG_PTR args) { std::lock_guard<std::mutex> global_lock(POLL_HANDLER_MUTEX); if (!_Events[pos].data.ptr) { return; } con* ccon = reinterpret_cast<con*>(_Events[pos].data.ptr); if (!ccon) return; if (!ccon) { return; } // Lock connection first (prevents concurrent Read/Write handlers on same con) std::unique_lock<std::mutex> conn_lock(ccon->event_mutex); if (ccon->csock) { try { if (epoll_ctl(_pollFD, EPOLL_CTL_DEL, ccon->csock->fd(), nullptr) < 0) { // Cache fd early; after close it may be invalid / reused int fd = -1; if (ccon->csock) fd = ccon->csock->fd(); // 1) Remove from epoll (ignore ENOENT / EBADF) if (fd >= 0) { if (epoll_ctl(_pollFD, EPOLL_CTL_DEL, fd, nullptr) < 0) { if (errno != ENOENT && errno != EBADF) { // Log, but continue cleanup anyway 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 epoll: " << errstr; // don't throw here; still must cleanup safely } } } // 2) Inform application layer (do NOT hold global map lock here) 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) { std::lock_guard<std::mutex> global_lock(POLL_HANDLER_MUTEX); if (fd >= 0) CONNECTIONS.erase(fd); } // 5) Clear epoll event slot pointer _Events[pos].data.ptr = nullptr; // 6) Destroy connection object conn_lock.unlock(); delete ccon; } Loading Loading
src/event/epoll.cpp +36 −26 Original line number Diff line number Diff line Loading @@ -342,43 +342,53 @@ namespace netplus { } void CloseEventHandler(int pos, const int tid, ULONG_PTR args) { std::lock_guard<std::mutex> global_lock(POLL_HANDLER_MUTEX); if (!_Events[pos].data.ptr) { return; } con* ccon = reinterpret_cast<con*>(_Events[pos].data.ptr); if (!ccon) return; if (!ccon) { return; } // Lock connection first (prevents concurrent Read/Write handlers on same con) std::unique_lock<std::mutex> conn_lock(ccon->event_mutex); if (ccon->csock) { try { if (epoll_ctl(_pollFD, EPOLL_CTL_DEL, ccon->csock->fd(), nullptr) < 0) { // Cache fd early; after close it may be invalid / reused int fd = -1; if (ccon->csock) fd = ccon->csock->fd(); // 1) Remove from epoll (ignore ENOENT / EBADF) if (fd >= 0) { if (epoll_ctl(_pollFD, EPOLL_CTL_DEL, fd, nullptr) < 0) { if (errno != ENOENT && errno != EBADF) { // Log, but continue cleanup anyway 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 epoll: " << errstr; // don't throw here; still must cleanup safely } } } // 2) Inform application layer (do NOT hold global map lock here) 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) { std::lock_guard<std::mutex> global_lock(POLL_HANDLER_MUTEX); if (fd >= 0) CONNECTIONS.erase(fd); } // 5) Clear epoll event slot pointer _Events[pos].data.ptr = nullptr; // 6) Destroy connection object conn_lock.unlock(); delete ccon; } Loading