Commit 398fdf51 authored by jan.koester's avatar jan.koester
Browse files

test

parent 31b8f356
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -240,4 +240,24 @@ namespace netplus {
        // waiting on this wakeup on those backends only resumes once some
        // other, unrelated event touches the connection.
        void requestWritablePoll(con &c);

        // Removes a connection from the event loop's fd tracking and returns its primary
        // socket WITHOUT closing it -- for a request handler that needs to take over a
        // connection's socket for something outside the normal read/dispatch/write cycle
        // (e.g. a WebSocket tunnel: once upgraded, bytes need to be relayed raw for the
        // connection's lifetime instead of being parsed as further HTTP). After this call
        // the event loop will never dispatch another event for this fd -- no more
        // IoEventHandler invocations, no re-arming. The caller owns the returned socket and
        // is responsible for eventually closing it.
        //
        // Returns nullptr if the connection has no socket (already closed/detached) or the
        // current backend doesn't implement this yet -- same per-backend caveat as
        // requestWritablePoll() above (epoll and kqueue implement it; select-based poll.cpp
        // and iocp.cpp are documented no-ops for now, since the one caller of this is new
        // and opt-in).
        //
        // PRECONDITION: caller holds c.event_mutex (true from within any RequestEvent
        // handler, which is invoked with it already held -- see requestWritablePoll's
        // identical precondition).
        std::unique_ptr<socket> detachConnection(con &c);
};
+26 −0
Original line number Diff line number Diff line
@@ -424,6 +424,14 @@ namespace netplus {
                            } else if (rcv > 0) {
                                c->RecvData.append(recvBuf.data.buf, rcv);
                                evconnection->RequestEvent(*c, tid, args);
                                if (!c->slots[0].csock) {
                                    // RequestEvent took ownership of this connection's
                                    // socket via detachConnection() (e.g. a WebSocket
                                    // tunnel handoff) -- nothing left here to read,
                                    // flush, or re-arm; EpollArmGuard's destructor
                                    // already no-ops on a null csock too.
                                    return;
                                }
                            }

                            if (wouldBlock) {
@@ -1074,4 +1082,22 @@ namespace netplus {
            epoll_ctl(c.ownerPollFd, EPOLL_CTL_ADD, fd, &ev);
    }

    std::unique_ptr<socket> detachConnection(con &c) {
        // Caller must hold c.event_mutex (see declaration in connection.h).
        if (c.slots.empty() || !c.slots[0].csock) return nullptr;
        int fd = c.slots[0].csock->fd();
        {
            // Once erased, no future epoll_wait() delivery for this fd can
            // find a connection to dispatch to (mirrors kqueue.cpp's
            // detachConnection -- see its longer comment for why no
            // explicit deregistration call is needed either: EPOLLONESHOT
            // already disabled the fd after the event we're currently
            // inside of, and EpollArmGuard's destructor already skips
            // re-arming once slots[0].csock is null).
            std::unique_lock<std::shared_mutex> lock(POLL_HANDLER_MUTEX);
            CONNECTIONS.erase(fd);
        }
        return std::move(c.slots[0].csock);
    }

} // namespace netplus
+4 −0
Original line number Diff line number Diff line
@@ -947,4 +947,8 @@ namespace netplus {
    std::shared_ptr<con> lookupConnection(int /*fd*/) { return nullptr; }
    void requestWritablePoll(con &) {}

    // Not yet implemented for this backend (see connection.h's doc comment) --
    // documented no-op, matching requestWritablePoll() above.
    std::unique_ptr<socket> detachConnection(con &) { return nullptr; }

} // namespace netplus
+29 −0
Original line number Diff line number Diff line
@@ -564,6 +564,14 @@ namespace netplus {
                            } else if (rcv > 0) {
                                c->RecvData.append(recvBuf.data.buf, rcv);
                                evconnection->RequestEvent(*c, tid, args);
                                if (!c->slots[0].csock) {
                                    // RequestEvent took ownership of this connection's
                                    // socket via detachConnection() (e.g. a WebSocket
                                    // tunnel handoff) -- nothing left here to read,
                                    // flush, or re-arm; KqueueArmGuard's destructor
                                    // already no-ops on a null csock too.
                                    return;
                                }
                            }

                            if (wouldBlock) {
@@ -1133,4 +1141,25 @@ namespace netplus {
        kevent(c.ownerPollFd, changes, 2, nullptr, 0, nullptr);
    }

    std::unique_ptr<socket> detachConnection(con &c) {
        // Caller must hold c.event_mutex (see declaration in connection.h).
        if (c.slots.empty() || !c.slots[0].csock) return nullptr;
        int fd = c.slots[0].csock->fd();
        {
            // Once erased, getConByFd() can never find this fd again, so
            // IoEventHandler's own entry guard (`if (!c || !c->slots[0].csock)
            // return;`) makes any *future* kevent for this fd (there
            // shouldn't be one -- EVFILT_READ/WRITE are EV_ONESHOT and we're
            // called from within the one that already fired, before it gets
            // re-armed) a safe no-op. No explicit EV_DELETE needed for the
            // same reason: a ONESHOT filter that already fired has nothing
            // left to delete, and KqueueArmGuard's destructor (which decides
            // whether to re-arm) already checks slots[0].csock and skips
            // re-arming once we null it below.
            std::unique_lock<std::shared_mutex> lock(POLL_HANDLER_MUTEX);
            CONNECTIONS.erase(fd);
        }
        return std::move(c.slots[0].csock);
    }

} // namespace netplus
+4 −0
Original line number Diff line number Diff line
@@ -1090,4 +1090,8 @@ namespace netplus {
    // feature that relies on this is new and opt-in.
    void requestWritablePoll(con &) {}

    // Not yet implemented for this backend (see connection.h's doc comment) --
    // documented no-op, matching requestWritablePoll() above.
    std::unique_ptr<socket> detachConnection(con &) { return nullptr; }

} // namespace netplus