implement acceptor thread shutdown

Sat, 03 Dec 2022 13:26:56 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 03 Dec 2022 13:26:56 +0100
changeset 446
240ed6f945ca
parent 445
834351da593b
child 447
45d1b02fa80b

implement acceptor thread shutdown

src/server/daemon/httplistener.c file | annotate | diff | comparison | revisions
src/server/daemon/httplistener.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/httplistener.c	Sat Dec 03 12:27:00 2022 +0100
+++ b/src/server/daemon/httplistener.c	Sat Dec 03 13:26:56 2022 +0100
@@ -30,15 +30,10 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
+
 #include <sys/shm.h>
-#include <sys/types.h>
 #include <sys/ipc.h>
-#include <sys/socket.h>
 #include <sys/file.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -48,12 +43,8 @@
 #include <signal.h>
 #include <pthread.h>
 
-#include <arpa/inet.h>
-#include <netinet/in.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/socket.h>
-#include <unistd.h>
 
 
 #include <cx/hash_map.h>
@@ -269,26 +260,25 @@
 #endif
     
     // bind server socket to address
-    struct sockaddr_in servaddr4;
-    struct sockaddr_in6 servaddr6;
+    union ws_socketaddr addr;
     struct sockaddr *servaddr;
     size_t servaddr_size;
     if(ipv4) {
         // ipv4
-        memset(&servaddr4, 0, sizeof(servaddr4));
-        servaddr4.sin_family = AF_INET;
-        servaddr4.sin_addr.s_addr = htonl(INADDR_ANY);
-        servaddr4.sin_port = htons(conf->port);
-        servaddr = (struct sockaddr *)&servaddr4;
-        servaddr_size = sizeof(servaddr4);
+        memset(&addr.addr4, 0, sizeof(addr.addr4));
+        addr.addr4.sin_family = AF_INET;
+        addr.addr4.sin_addr.s_addr = htonl(INADDR_ANY);
+        addr.addr4.sin_port = htons(conf->port);
+        servaddr = (struct sockaddr *)&addr.addr4;
+        servaddr_size = sizeof(addr.addr4);
     } else {
         // ipv6
-        memset(&servaddr6, 0, sizeof(servaddr6));
-        servaddr6.sin6_family = AF_INET6;
-        servaddr6.sin6_addr = in6addr_any;
-        servaddr6.sin6_port = htons(conf->port);
-        servaddr = (struct sockaddr *)&servaddr6;
-        servaddr_size = sizeof(servaddr6);
+        memset(&addr.addr6, 0, sizeof(addr.addr6));
+        addr.addr6.sin6_family = AF_INET6;
+        addr.addr6.sin6_addr = in6addr_any;
+        addr.addr6.sin6_port = htons(conf->port);
+        servaddr = (struct sockaddr *)&addr.addr6;
+        servaddr_size = sizeof(addr.addr6);
     }
     
     if(bind(s, servaddr, servaddr_size)) {
@@ -310,6 +300,13 @@
     }
     ZERO(wssocket, sizeof(WSSocket));
     wssocket->socket = s;
+    wssocket->addr = addr;
+    if(ipv4) {
+        wssocket->sockaddr = (struct sockaddr *)&wssocket->addr.addr4;
+    } else {
+        wssocket->sockaddr = (struct sockaddr *)&wssocket->addr.addr6;
+    }
+    wssocket->sockaddr_size = servaddr_size;
     
     return wssocket;
 }
@@ -476,10 +473,52 @@
     listener->next = next;
 }
 
+int http_listener_connect(HttpListener *listener, WSBool ipv6) {
+    int domain = ipv6 ? AF_INET6 : AF_INET;
+    int client = socket(domain, SOCK_STREAM, 0);
+    if(client < 0) {
+        return -1;
+    }
+    
+    struct sockaddr *sockaddr;
+    size_t sockaddr_size;
+    if(ipv6) {
+        sockaddr = listener->server_socket6->sockaddr;
+        sockaddr_size = listener->server_socket6->sockaddr_size;
+    } else {
+        sockaddr = listener->server_socket->sockaddr;
+        sockaddr_size = listener->server_socket->sockaddr_size;
+    }
+    
+    if(connect(client, sockaddr, sockaddr_size) < 0) {
+        close(client);
+        return -1;
+    }
+    
+    return client;
+}
 
 
 void http_listener_shutdown_acceptors(HttpListener *listener) {
-    // not implemented yet
+    // 
+    
+    for(int i=0;i<listener->nacceptors;i++) {
+        listener->acceptors[i]->exit = TRUE;
+        int client4 = http_listener_connect(listener, FALSE);
+        if(client4 < 0) {
+            log_ereport(LOG_FAILURE, "http_listener_shutdown_acceptors: cannot connect to ipv4 server socket: %s", strerror(errno));
+        } else {
+            close(client4);
+        }
+        
+        listener->acceptors6[i]->exit = TRUE;
+        int client6 = http_listener_connect(listener, TRUE);
+        if(client6 < 0) {
+            log_ereport(LOG_FAILURE, "http_listener_shutdown_acceptors: cannot connect to ipv6 server socket: %s", strerror(errno));
+        } else {
+            close(client6);
+        }
+    }
 }
 
 
@@ -547,6 +586,11 @@
         log_ereport(LOG_DEBUG, "acceptor: %p listener: %p: accept(): %d", acceptor, acceptor->listener, clientfd);
         if (clientfd == -1) {
             log_ereport(LOG_FAILURE, "accept %s failed: %s", acceptor->ipv6 ? "ipv6" : "ipv4", strerror(errno));
+            
+            if(acceptor->exit) {
+                log_ereport(LOG_VERBOSE, "acceptor thread %p: listener: %p exit", acceptor, acceptor->listener);
+                break;
+            }
             continue;
         }
                  
@@ -613,13 +657,12 @@
         
         if(acceptor_exit || acceptor->exit) {
             // this acceptor is outdated
-            log_ereport(LOG_VERBOSE, "acceptor thread %p: exit", (void*)acceptor->tid);
+            log_ereport(LOG_VERBOSE, "acceptor thread %p: listener: %p exit", acceptor, acceptor->listener);
             break;
         }
     }
     
     acceptor->running = FALSE;
-    log_ereport(LOG_DEBUG, "acceptor: %p listener %p exit thread", acceptor, acceptor->listener);
     
     cfg_unref(acceptor->listener->cfg);
     
--- a/src/server/daemon/httplistener.h	Sat Dec 03 12:27:00 2022 +0100
+++ b/src/server/daemon/httplistener.h	Sat Dec 03 13:26:56 2022 +0100
@@ -34,6 +34,13 @@
 #include "config.h"
 #include "../util/systems.h"
 
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <unistd.h>
+
 #include <openssl/bio.h> 
 #include <openssl/ssl.h> 
 #include <openssl/err.h> 
@@ -112,7 +119,15 @@
     // TODO: ssl/tls cipher, ... config
 };
 
+union ws_socketaddr {
+    struct sockaddr_in  addr4;
+    struct sockaddr_in6 addr6;
+};
+
 struct _ws_socket {
+    union ws_socketaddr addr;
+    struct sockaddr *sockaddr;
+    size_t sockaddr_size;
     int socket;
     WSBool listening;
     HttpSSL *ssl;
@@ -143,7 +158,15 @@
 void http_listener_set_next(HttpListener *listener, HttpListener *next);
 
 /*
+ * Connect to the listener's server socket
+ * Returns a file descriptor or -1
+ */
+int http_listener_connect(HttpListener *listener, WSBool ipv6);
+
+/*
  * shutdown all acceptor threads
+ * this should be called, before any new acceptors for the same socket
+ * are started
  */
 void http_listener_shutdown_acceptors(HttpListener *listener);
 

mercurial