add functions to stop event handlers

Thu, 15 Aug 2024 21:46:57 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 15 Aug 2024 21:46:57 +0200
changeset 547
280bf87c8689
parent 546
5494c28db896
child 548
40ecc0a6b280

add functions to stop event handlers

src/server/daemon/event.c file | annotate | diff | comparison | revisions
src/server/daemon/event.h file | annotate | diff | comparison | revisions
src/server/daemon/event_bsd.c file | annotate | diff | comparison | revisions
src/server/daemon/event_linux.c file | annotate | diff | comparison | revisions
src/server/daemon/event_linux.h file | annotate | diff | comparison | revisions
src/server/daemon/event_solaris.c file | annotate | diff | comparison | revisions
--- a/src/server/daemon/event.c	Tue Aug 13 20:08:13 2024 +0200
+++ b/src/server/daemon/event.c	Thu Aug 15 21:46:57 2024 +0200
@@ -78,6 +78,13 @@
     return ret;
 }
 
+void evhandler_close(EVHandler *h) {
+    for(int i=0;i<h->numins;i++) {
+        ev_instance_close(h->instances[i]);
+    }
+    h->numins = 0;
+}
+
 /*
  * checks if there is at least one event handler and a default handler
  * if necessary, check_event_handler_cfg() creates a default event handler
--- a/src/server/daemon/event.h	Tue Aug 13 20:08:13 2024 +0200
+++ b/src/server/daemon/event.h	Thu Aug 15 21:46:57 2024 +0200
@@ -89,6 +89,7 @@
 } EventHandler;
 
 
+void evhandler_close(EVHandler *h);
 
 int create_event_handler(EventHandlerConfig *cfg);
 
@@ -107,6 +108,8 @@
 
 /* implementation in event_$platform */
 EVHandler* evhandler_create(EventHandlerConfig *cfg);
+void ev_instance_close(EventHandler *h);
+void ev_instance_shutdown(EventHandler *h);
 
 int ev_pollin(EventHandler *h, int fd, Event *event);
 int ev_pollout(EventHandler *h, int fd, Event *event);
--- a/src/server/daemon/event_bsd.c	Tue Aug 13 20:08:13 2024 +0200
+++ b/src/server/daemon/event_bsd.c	Thu Aug 15 21:46:57 2024 +0200
@@ -64,6 +64,19 @@
     return ev;
 }
 
+static volatile int ev_close = 0;
+
+void ev_instance_close(EventHandler *h) {
+    EventHandlerKqueue *ev = (EventHandlerKqueue*)h;
+    close(ev->kqueue);
+    ev_close = 1;
+}
+
+// unique event addr that indicates shutdown
+static Event shutdown_event;
+void ev_instance_shutdown(EventHandler *h) {
+    event_send(h, &shutdown_event);
+}
 
 void ev_handle_events(EventHandlerKqueue *ev) {
     EventHandler *h = (EventHandler*)ev;
@@ -81,7 +94,12 @@
         // wait for events
         int nev = kevent(ev->kqueue, changes, numchanges, events, EV_MAX_EVENTS, &timeout);  
         if(nev == -1) {
-            log_ereport(LOG_FAILURE, "kevent: %s", strerror(errno));
+            if(errno != EINTR) {
+                if(!ev_close) {
+                    log_ereport(LOG_CATASTROPHE, "kevent failed: %s", strerror(errno));
+                }
+                break;
+            }
             continue;
         }
         
@@ -140,6 +158,8 @@
                         }
                     }
                 }
+            } else if(event == &shutdown_event) {
+                ev_instance_close(h);
             }
         }
         // call event finish handlers
@@ -156,6 +176,8 @@
             nsapi_saf_return(ret.sn, ret.rq, ret.ret);
         }
     }
+    
+    free(ev);
 }
 
 int ev_pollin(EventHandler *h, int fd, Event *event) {
--- a/src/server/daemon/event_linux.c	Tue Aug 13 20:08:13 2024 +0200
+++ b/src/server/daemon/event_linux.c	Thu Aug 15 21:46:57 2024 +0200
@@ -103,6 +103,20 @@
     return ev;
 }
 
+static volatile int ev_close = 0;
+
+void ev_instance_close(EventHandler *h) {
+    EventHandlerLinux *ev = (EventHandlerLinux*)h;
+    ev_close = 1;
+    close(ev->ep);
+}
+
+// unique event addr that indicates shutdown
+static Event shutdown_event;
+void ev_instance_shutdown(EventHandler *h) {
+    event_send(h, &shutdown_event);
+}
+
 void ev_handle_events(EventHandlerLinux *ev) {
     EventHandler *h = (EventHandler*)ev;
     int ep = ev->ep;
@@ -113,7 +127,8 @@
     size_t queue_len = 0;
     
     int loop_ctn = 0;
-    for(;;) {
+    int ev_shutdown = 0;
+    while(!ev_shutdown) {
         // if ev->event_queue contains events, we process them first
         // otherwise we get events from epoll
         int ret = 0;
@@ -150,8 +165,13 @@
         } else {
             // wait for events
             ret = epoll_wait(ep, events, EV_MAX_EVENTS, EV_IDLE_TIMEOUT * 1000);
-            if(ret == -1 && errno != EINTR) {
-                log_ereport(LOG_FAILURE, "epoll_wait failed: %s", strerror(errno));
+            if(ret == -1) {
+                if(errno != EINTR) {
+                    if(!ev_close) {
+                        log_ereport(LOG_CATASTROPHE, "epoll_wait failed: %s", strerror(errno));
+                    }
+                    break;
+                }
                 continue;
             }
         }
@@ -211,6 +231,8 @@
                         }
                     }
                 }
+            } else if(event == &shutdown_event) {
+                ev_instance_close(h);
             }
         }
         // call event finish handlers
@@ -232,6 +254,21 @@
             loop_ctn = 0;
         }
     }
+    
+    // epoll fd is already closed
+    
+    ev_queue_free(ev->queue_begin);
+    pthread_mutex_destroy(&ev->queue_lock);
+    close(ev->event_fd);
+    free(ev);
+}
+
+void ev_queue_free(EventQueue *queue) {
+    while(queue) {
+        EventQueue *next = queue->next;
+        free(queue);
+        queue = next;
+    }
 }
 
 int ev_convert2sys_events(int events) {
--- a/src/server/daemon/event_linux.h	Tue Aug 13 20:08:13 2024 +0200
+++ b/src/server/daemon/event_linux.h	Thu Aug 15 21:46:57 2024 +0200
@@ -108,6 +108,8 @@
 
 int ev_convert2sys_events(int events);
 
+void ev_queue_free(EventQueue *queue);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/src/server/daemon/event_solaris.c	Tue Aug 13 20:08:13 2024 +0200
+++ b/src/server/daemon/event_solaris.c	Thu Aug 15 21:46:57 2024 +0200
@@ -64,6 +64,20 @@
     return ev;
 }
 
+static volatile int ev_close = 0;
+
+void ev_instance_close(EventHandler *h) {
+    EventHandlerSolaris *ev = (EventHandlerSolaris*)h;
+    close(ev->port);
+    ev_close = 1;
+}
+
+// unique event addr that indicates shutdown
+static Event shutdown_event;
+void ev_instance_shutdown(EventHandler *h) {
+    event_send(h, &shutdown_event);
+}
+
 
 void ev_handle_events(EventHandlerSolaris *ev) {
     EventHandler *h = (EventHandler*)ev;
@@ -78,8 +92,12 @@
         uint_t nev = 1;
         int ret = port_getn(ev->port, events, EV_MAX_EVENTS, &nev, &timeout);
         if(ret == -1) {
-            // TODO: check for error
-            perror("port_getn");
+            if(errno != EINTR && errno != ETIME) {
+                if(!ev_close) {
+                    log_ereport(LOG_CATASTROPHE, "port_getn failed: %s", strerror(errno));
+                }
+                break;
+            }
             continue;
         }
         
@@ -120,6 +138,8 @@
                     } else if(event->finish) {
                         event->finish(h, event);
                     }
+                } else if(event == &shutdown_event) {
+                    ev_instance_close(h);
                 }
             }  
         }
@@ -137,6 +157,8 @@
             nsapi_saf_return(ret.sn, ret.rq, ret.ret);
         }
     }
+    
+    free(ev);
 }
 
 int ev_convert2sys_events(int events) {

mercurial