Refactor queue-event-handling to be pointer-centric - quark - quark web server
 (HTM) git clone git://git.suckless.org/quark
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 35e3b69d60f337724163e9543b5728b907ce34dd
 (DIR) parent f1892c4dffa7df6995cd8c9ebd47e0ce7f0e457e
 (HTM) Author: Laslo Hunhold <dev@frign.de>
       Date:   Sun, 31 Jan 2021 11:33:46 +0100
       
       Refactor queue-event-handling to be pointer-centric
       
       This is one aspect where we can see that kqueue(2) is superior to
       epoll(7). While kqueue(2) allows you to both store a pointer and read
       out the fd of an event in the ready-list, epoll(7) only provides you
       with one of the two (by only offering a union-type-field where you
       either store an fd or a pointer).
       
       Previously, wrapper functions would allow to extract either from any
       event, which was only non-hacky in the OpenBSD-case, because nothing
       stopped you from reading the "fd" from the union that actually was
       assigned as a pointer. The distinction was there in the first place
       because we are listening on the main incoming socket and other "client"-
       sockets at the same time. The main-socket-events contained the socket-fd
       and the client-sockets contained the connection-struct-pointer. Now, we
       just set the data-pointer of the main socket to NULL to indicate it,
       yielding a much more refined usage with one fewer way to screw things
       up.
       
       Signed-off-by: Laslo Hunhold <dev@frign.de>
       
       Diffstat:
         M main.c                              |      31 +++++++++++++++----------------
         M queue.c                             |      32 +++++--------------------------
         M queue.h                             |       3 +--
       
       3 files changed, 21 insertions(+), 45 deletions(-)
       ---
 (DIR) diff --git a/main.c b/main.c
       @@ -210,9 +210,9 @@ static void *
        thread_method(void *data)
        {
                queue_event *event = NULL;
       -        struct connection *connection, *c;
       +        struct connection *connection, *c, *newc;
                struct worker_data *d = (struct worker_data *)data;
       -        int qfd, fd;
       +        int qfd;
                ssize_t nready;
                size_t i;
        
       @@ -226,7 +226,7 @@ thread_method(void *data)
                        exit(1);
                }
        
       -        /* add insock to the interest list */
       +        /* add insock to the interest list (with data=NULL) */
                if (queue_add_fd(qfd, d->insock, QUEUE_EVENT_IN, 1, NULL) < 0) {
                        exit(1);
                }
       @@ -244,12 +244,12 @@ thread_method(void *data)
        
                        /* handle events */
                        for (i = 0; i < (size_t)nready; i++) {
       -                        if (queue_event_is_dropped(&event[i])) {
       -                                fd = queue_event_get_fd(&event[i]);
       +                        c = queue_event_get_data(&event[i]);
        
       -                                if (fd != d->insock) {
       -                                        memset(queue_event_get_ptr(&event[i]),
       -                                               0, sizeof(struct connection));
       +                        if (queue_event_is_dropped(&event[i])) {
       +                                if (c != NULL) {
       +                                        queue_rem_fd(qfd, c->fd);
       +                                        close_connection(c);
                                        }
        
                                        printf("dropped a connection\n");
       @@ -257,11 +257,11 @@ thread_method(void *data)
                                        continue;
                                }
        
       -                        if (queue_event_get_fd(&event[i]) == d->insock) {
       +                        if (c == NULL) {
                                        /* add new connection to the interest list */
       -                                if (!(c = accept_connection(d->insock,
       -                                                            connection,
       -                                                            d->nslots))) {
       +                                if (!(newc = accept_connection(d->insock,
       +                                                               connection,
       +                                                               d->nslots))) {
                                                /*
                                                 * the socket is either blocking
                                                 * or something failed.
       @@ -275,20 +275,19 @@ thread_method(void *data)
                                         * (we want IN, because we start
                                         * with receiving the header)
                                         */
       -                                if (queue_add_fd(qfd, c->fd,
       +                                if (queue_add_fd(qfd, newc->fd,
                                                         QUEUE_EVENT_IN,
       -                                                 0, c) < 0) {
       +                                                 0, newc) < 0) {
                                                /* not much we can do here */
                                                continue;
                                        }
                                } else {
       -                                c = queue_event_get_ptr(&event[i]);
       -
                                        /* serve existing connection */
                                        serve_connection(c, d->srv);
        
                                        if (c->fd == 0) {
                                                /* we are done */
       +                                        memset(c, 0, sizeof(struct connection));
                                                continue;
                                        }
        
 (DIR) diff --git a/queue.c b/queue.c
       @@ -65,14 +65,8 @@ queue_add_fd(int qfd, int fd, enum queue_event_type t, int shared,
                                break;
                        }
        
       -                /* set data */
       -                if (data == NULL) {
       -                        /* the data is the fd itself */
       -                        e.data.fd = fd;
       -                } else {
       -                        /* set data pointer */
       -                        e.data.ptr = (void *)data;
       -                }
       +                /* set data pointer */
       +                e.data.ptr = (void *)data;
        
                        /* register fd in the interest list */
                        if (epoll_ctl(qfd, EPOLL_CTL_ADD, fd, &e) < 0) {
       @@ -124,14 +118,8 @@ queue_mod_fd(int qfd, int fd, enum queue_event_type t, const void *data)
                                break;
                        }
        
       -                /* set data */
       -                if (data == NULL) {
       -                        /* the data is the fd itself */
       -                        e.data.fd = fd;
       -                } else {
       -                        /* set data pointer */
       -                        e.data.ptr = (void *)data;
       -                }
       +                /* set data pointer */
       +                e.data.ptr = (void *)data;
        
                        /* register fd in the interest list */
                        if (epoll_ctl(qfd, EPOLL_CTL_MOD, fd, &e) < 0) {
       @@ -208,18 +196,8 @@ queue_wait(int qfd, queue_event *e, size_t elen)
                return nready;
        }
        
       -int
       -queue_event_get_fd(const queue_event *e)
       -{
       -        #ifdef __linux__
       -                return e->data.fd;
       -        #else
       -                return e->ident;
       -        #endif
       -}
       -
        void *
       -queue_event_get_ptr(const queue_event *e)
       +queue_event_get_data(const queue_event *e)
        {
                #ifdef __linux__
                        return e->data.ptr;
 (DIR) diff --git a/queue.h b/queue.h
       @@ -26,8 +26,7 @@ int queue_mod_fd(int, int, enum queue_event_type, const void *);
        int queue_rem_fd(int, int);
        ssize_t queue_wait(int, queue_event *, size_t);
        
       -int queue_event_get_fd(const queue_event *);
       -void *queue_event_get_ptr(const queue_event *);
       +void *queue_event_get_data(const queue_event *);
        
        int queue_event_is_dropped(const queue_event *e);