SAMBA4 event loop

Stefan (metze) Metzmacher metze at metzemix.de
Tue Sep 9 10:54:42 GMT 2003


Hi tridge,

I'm using samba4's event_loop for my imap server (emil-surfer).

And I found a bug in it..:-(

we call select even if there're no fd_events left...

I use the attached patch in my server.

- I move calc_maxfd in only one place

- I call select only if (ev->events)

- I add the expect fd's to select
   (I'm not using it but I want modules to be able to use this)


Index: incdir/mx-events.h
===================================================================
RCS file: /home/CVSROOT/emil-surfer/incdir/mx-events.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- incdir/mx-events.h  2003/09/09 10:42:48     1.2
+++ incdir/mx-events.h  2003/09/09 10:43:20     1.3
@@ -69,7 +69,9 @@
         } exit;
  };

+#define EVENT_INVALID_MAXFD (-1)

  /* bits for fd_event.flags */
-#define EVENT_FD_READ 1
-#define EVENT_FD_WRITE 2
+#define EVENT_FD_READ  0x0001
+#define EVENT_FD_WRITE 0x0002
+#define EVENT_FD_EXPECT        0x0004
Index: server/events.c
===================================================================
RCS file: /home/CVSROOT/emil-surfer/server/events.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- server/events.c     2003/09/08 06:33:44     1.1
+++ server/events.c     2003/09/09 10:37:04     1.2
@@ -132,8 +132,6 @@
                     e->fd == e1->fd &&
                     e->handler == e1->handler) {
                         e->ref_count--;
-                       /* possibly calculate the new maxfd */
-                       calc_maxfd(ev);
                         return True;
                 }
         }
@@ -151,7 +149,6 @@
                         e->ref_count--;
                 }
         }
-       calc_maxfd(ev);
  }

  /*
@@ -166,7 +163,6 @@
                         e->ref_count--;
                 }
         }
-       calc_maxfd(ev);
  }


@@ -258,7 +254,7 @@
         t = time(NULL);

         while (ev->fd_events && !ev->exit.exit_now) {
-               fd_set r_fds, w_fds;
+               fd_set r_fds, w_fds, e_fds;
                 struct fd_event *fe;
                 struct loop_event *le;
                 struct timed_event *te;
@@ -283,12 +279,16 @@
                 ZERO_STRUCT(tval);
                 FD_ZERO(&r_fds);
                 FD_ZERO(&w_fds);
+               FD_ZERO(&e_fds);

                 /* setup any fd events */
                 for (fe=ev->fd_events; fe; ) {
                         struct fd_event *next = fe->next;
                         if (fe->ref_count == 0) {
                                 DLIST_REMOVE(ev->fd_events, fe);
+                               if (ev->maxfd == fe->fd) {
+                                       ev->maxfd = EVENT_INVALID_MAXFD;
+                               }
                                 free(fe);
                         } else {
                                 if (fe->flags & EVENT_FD_READ) {
@@ -297,6 +297,9 @@
                                 if (fe->flags & EVENT_FD_WRITE) {
                                         FD_SET(fe->fd, &w_fds);
                                 }
+                               if (fe->flags & EVENT_FD_EXPECT) {
+                                       FD_SET(fe->fd, &e_fds);
+                               }
                         }
                         fe = next;
                 }
@@ -316,33 +319,39 @@
                         }
                 }

+               if (ev->maxfd == EVENT_INVALID_MAXFD) {
+                       calc_maxfd(ev);
+               }
+
+               if (ev->fd_events) {
+                       selrtn = sys_select(ev->maxfd+1, &r_fds, &w_fds, 
&e_fds, &tval);

-               selrtn = sys_select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval);
+                       t = time(NULL);

-               t = time(NULL);
+                       if (selrtn == -1 && errno == EBADF) {
+                               /* the socket is dead! this should never
+                                  happen as the socket should have first been
+                                  made readable and that should have removed
+                                  the event, so this must be a bug. This is a
+                                  fatal error. */
+                               DEBUG(0,("EBADF on event_loop_wait - 
exiting\n"));
+                               return -1;
+                       }

-               if (selrtn == -1 && errno == EBADF) {
-                       /* the socket is dead! this should never
-                          happen as the socket should have first been
-                          made readable and that should have removed
-                          the event, so this must be a bug. This is a
-                          fatal error. */
-                       DEBUG(0,("EBADF on event_loop_wait - exiting\n"));
-                       return -1;
-               }
-
-               if (selrtn > 0) {
-                       /* at least one file descriptor is ready - check
-                          which ones and call the handler, being careful 
to allow
-                          the handler to remove itself when called */
-                       for (fe=ev->fd_events; fe; fe=fe->next) {
-                               uint16 flags = 0;
-                               if (FD_ISSET(fe->fd, &r_fds)) flags |= 
EVENT_FD_READ;
-                               if (FD_ISSET(fe->fd, &w_fds)) flags |= 
EVENT_FD_WRITE;
-                               if (fe->ref_count && flags) {
-                                       fe->ref_count++;
-                                       fe->handler(ev, fe, t, flags);
-                                       fe->ref_count--;
+                       if (selrtn > 0) {
+                               /* at least one file descriptor is ready - 
check
+                                  which ones and call the handler, being 
careful to allow
+                                  the handler to remove itself when called */
+                               for (fe=ev->fd_events; fe; fe=fe->next) {
+                                       uint16 flags = 0;
+                                       if (FD_ISSET(fe->fd, &r_fds)) flags 
|= EVENT_FD_READ;
+                                       if (FD_ISSET(fe->fd, &w_fds)) flags 
|= EVENT_FD_WRITE;
+                                       if (FD_ISSET(fe->fd, &e_fds)) flags 
|= EVENT_FD_EXPECT;
+                                       if (fe->ref_count && flags) {
+                                               fe->ref_count++;
+                                               fe->handler(ev, fe, t, flags);
+                                               fe->ref_count--;
+                                       }
                                 }
                         }
                 }



metze
-----------------------------------------------------------------------------
Stefan "metze" Metzmacher <metze at metzemix.de> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: events-01.diff
Type: application/octet-stream
Size: 4118 bytes
Desc: not available
Url : http://lists.samba.org/archive/samba-technical/attachments/20030909/7abeb538/events-01.obj


More information about the samba-technical mailing list