tReworking the socket closing handling. - geomyidae - A small C-based gopherd. (gopher://bitreich.org/1/scm/geomyidae)
 (HTM) git clone git://r-36.net/geomyidae
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit ecf782f0557effe122f791f839a509ec428d236e
 (DIR) parent f4cac1fea572c34eaf23baef928d7aa313ae9ccf
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Wed,  7 Feb 2018 19:57:42 +0100
       
       Reworking the socket closing handling.
       
       Thanks Evil_Bob for much input.
       
       Geomyidae now supports the ugly event code of curl.
       
       Diffstat:
         handlr.c                            |       1 -
         ind.c                               |      29 ++++++++++++++++++++++++++---
         ind.h                               |       2 ++
         main.c                              |      30 ++++++++++++++++++++----------
       
       4 files changed, 48 insertions(+), 14 deletions(-)
       ---
 (DIR) diff --git a/handlr.c b/handlr.c
       t@@ -116,7 +116,6 @@ handlebin(int sock, char *file, char *port, char *base, char *args,
                if (fd >= 0) {
                        if (xsendfile(fd, sock) < 0)
                                perror("sendfile");
       -                close(fd);
                }
        }
        
 (DIR) diff --git a/ind.c b/ind.c
       t@@ -16,15 +16,18 @@
        #include <netinet/in.h>
        #include <netinet/tcp.h>
        #include <arpa/inet.h>
       +#include <sys/ioctl.h>
        
       -/* for sendfile(2) */
       +/* for sendfile(2) and SIOCOUTQ */
        #ifdef __linux__
        #include <sys/sendfile.h>
       +#include <linux/sockios.h>
        #elif defined(__FreeBSD__) || defined(__DragonFly__)
        #include <sys/types.h>
        #include <sys/uio.h>
        #endif
        
       +#include "arg.h"
        #include "ind.h"
        #include "handlr.h"
        
       t@@ -53,6 +56,25 @@ filetype type[] = {
        };
        
        int
       +pendingbytes(int sock)
       +{
       +        int pending;
       +
       +        pending = 0;
       +        ioctl(sock, SIOCOUTQ, &pending);
       +
       +        return pending;
       +}
       +
       +void
       +waitforpendingbytes(int sock)
       +{
       +
       +        while (pendingbytes(sock) > 0)
       +                usleep(10);
       +}
       +
       +int
        xsendfile(int fd, int sock)
        {
                struct stat st;
       t@@ -60,6 +82,8 @@ xsendfile(int fd, int sock)
                size_t bufsiz = BUFSIZ, count = 0;
                int len, sent, optval;
        
       +        USED(optval);
       +
        /* Tell the kernel to not send small packets on every write. */
        #ifdef TCP_CORK
                optval = 1;
       t@@ -94,12 +118,11 @@ xsendfile(int fd, int sock)
                count = 0;
        #endif
        
       -        if (count == 0) {
       +        if (count > 0) {
                        sendb = xmalloc(bufsiz);
                        while ((len = read(fd, sendb, bufsiz)) > 0) {
                                while (len > 0) {
                                        if ((sent = send(sock, sendb, len, 0)) < 0) {
       -                                        close(fd);
                                                free(sendb);
                                                return -1;
                                        }
 (DIR) diff --git a/ind.h b/ind.h
       t@@ -39,6 +39,8 @@ char *xstrdup(const char *str);
        int xsendfile(int, int);
        Indexs *scanfile(char *fname);
        Elems *getadv(char *str);
       +int pendingbytes(int sock);
       +void waitforpendingbytes(int sock);
        int printelem(int fd, Elems *el, char *addr, char *port);
        void addindexs(Indexs *idx, Elems *el);
        void addelem(Elems *e, char *s);
 (DIR) diff --git a/main.c b/main.c
       t@@ -15,6 +15,8 @@
        #include <sys/stat.h>
        #include <sys/wait.h>
        #include <sys/types.h>
       +#include <sys/ioctl.h>
       +#include <linux/sockios.h>
        #include <signal.h>
        #include <string.h>
        #include <strings.h>
       t@@ -39,7 +41,6 @@ enum {
        
        int glfd = -1;
        int loglvl = 15;
       -int running = 1;
        int listfd = -1;
        int revlookup = 1;
        char *logfile = nil;
       t@@ -121,8 +122,11 @@ handlerequest(int sock, char *base, char *ohost, char *port, char *clienth,
                args = nil;
        
                len = recv(sock, recvb, sizeof(recvb)-1, 0);
       -        if (len <= 0)
       +        if (len <= 0) {
       +                if (len < 0)
       +                        perror("recv");
                        return;
       +        }
        
                c = strchr(recvb, '\r');
                if (c)
       t@@ -293,6 +297,7 @@ getlistenfd(struct addrinfo *hints, char *bindip, char *port)
                                continue;
                        if (setsockopt(listfd, SOL_SOCKET, SO_REUSEADDR, &on,
                                                sizeof(on)) < 0) {
       +                        close(listfd);
                                break;
                        }
        
       t@@ -402,6 +407,9 @@ main(int argc, char *argv[])
                        usage();
                } ARGEND;
        
       +        if (argc != 0)
       +                usage();
       +
                if (ohost == nil) {
                        ohost = xcalloc(1, 513);
                        if (gethostname(ohost, 512) < 0) {
       t@@ -507,17 +515,12 @@ main(int argc, char *argv[])
                initsignals();
        
                cltlen = sizeof(clt);
       -        while (running) {
       +        while (1) {
                        sock = accept(listfd, (struct sockaddr *)&clt, &cltlen);
                        if (sock < 0) {
                                switch (errno) {
                                case ECONNABORTED:
                                case EINTR:
       -                                if (!running) {
       -                                        shutdown(listfd, SHUT_RDWR);
       -                                        close(listfd);
       -                                        return 0;
       -                                }
                                        continue;
                                default:
                                        perror("accept");
       t@@ -542,6 +545,8 @@ main(int argc, char *argv[])
                                shutdown(sock, SHUT_RDWR);
                                break;
                        case 0:
       +                        close(listfd);
       +
                                signal(SIGHUP, SIG_DFL);
                                signal(SIGQUIT, SIG_DFL);
                                signal(SIGINT, SIG_DFL);
       t@@ -550,15 +555,20 @@ main(int argc, char *argv[])
        
                                handlerequest(sock, base, ohost, sport, clienth,
                                                        clientp);
       +
       +                        waitforpendingbytes(sock);
       +
                                shutdown(sock, SHUT_RDWR);
                                close(sock);
       +
       +                        if (loglvl & CONN)
       +                                logentry(clienth, clientp, "-", "disconnected");
       +
                                return 0;
                        default:
                                break;
                        }
                        close(sock);
       -                if (loglvl & CONN)
       -                        logentry(clienth, clientp, "-", "disconnected");
                }
        
                shutdown(listfd, SHUT_RDWR);