Reworking the socket closing handling. - geomyidae - A small C-based gopherd. (HTM) git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (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: M handlr.c | 1 - M ind.c | 29 ++++++++++++++++++++++++++--- M ind.h | 2 ++ M main.c | 30 ++++++++++++++++++++---------- 4 files changed, 48 insertions(+), 14 deletions(-) --- (DIR) diff --git a/handlr.c b/handlr.c @@ -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 @@ -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" @@ -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; @@ -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; @@ -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 @@ -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 @@ -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> @@ -39,7 +41,6 @@ enum { int glfd = -1; int loglvl = 15; -int running = 1; int listfd = -1; int revlookup = 1; char *logfile = nil; @@ -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) @@ -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; } @@ -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) { @@ -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"); @@ -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); @@ -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);