Fix segfault in scheduler loop because of missing lazy removal of elements in schedul...
authorHenning Rogge <hrogge@googlemail.com>
Thu, 22 Apr 2010 15:32:38 +0000 (17:32 +0200)
committerHenning Rogge <hrogge@googlemail.com>
Thu, 22 Apr 2010 15:32:38 +0000 (17:32 +0200)
src/interfaces.c
src/scheduler.c
src/unix/ifnet.c

index 4497514..abc8a44 100644 (file)
@@ -372,7 +372,7 @@ olsr_remove_interface(struct olsr_if * iface)
   struct interface *ifp, *tmp_ifp;
   ifp = iface->interf;
 
-  OLSR_PRINTF(1, "Removing interface %s\n", iface->name);
+  OLSR_PRINTF(1, "Removing interface %s (%d)\n", iface->name, ifp->if_index);
   olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name);
 
   olsr_delete_link_entry_by_ip(&ifp->ip_addr);
@@ -427,13 +427,11 @@ olsr_remove_interface(struct olsr_if * iface)
   iface->interf = NULL;
 
   /* Close olsr socket */
-  close(ifp->olsr_socket);
   remove_olsr_socket(ifp->olsr_socket, &olsr_input, NULL);
+  close(ifp->olsr_socket);
 
-  if (ifp->send_socket != ifp->olsr_socket) {
-    close(ifp->send_socket);
-    remove_olsr_socket(ifp->send_socket, &olsr_input, NULL);
-  }
+  remove_olsr_socket(ifp->send_socket, &olsr_input, NULL);
+  close(ifp->send_socket);
 
   /* Free memory */
   free(ifp->int_name);
index 9a9319f..eae4d85 100644 (file)
@@ -215,8 +215,10 @@ remove_olsr_socket(int fd, socket_handler_func pf_pr, socket_handler_func pf_imm
 
   OLSR_FOR_ALL_SOCKETS(entry) {
     if (entry->fd == fd && entry->process_immediate == pf_imm && entry->process_pollrate == pf_pr) {
-      list_remove(&entry->socket_node);
-      free(entry);
+      /* just mark this node as "deleted", it will be cleared later at the end of handle_fds() */
+      entry->process_immediate = NULL;
+      entry->process_pollrate = NULL;
+      entry->flags = 0;
       return 1;
     }
   }
@@ -340,6 +342,7 @@ poll_sockets(void)
 static void
 handle_fds(uint32_t next_interval)
 {
+  struct olsr_socket_entry *entry;
   struct timeval tvp;
   int32_t remaining;
 
@@ -363,7 +366,6 @@ handle_fds(uint32_t next_interval)
 
   /* do at least one select */
   for (;;) {
-    struct olsr_socket_entry *entry;
     fd_set ibits, obits;
     int n, hfd = 0, fdsets = 0;
     FD_ZERO(&ibits);
@@ -390,7 +392,7 @@ handle_fds(uint32_t next_interval)
 
     if (hfd == 0 && (long)remaining <= 0) {
       /* we are over the interval and we have no fd's. Skip the select() etc. */
-      return;
+      break;
     }
 
     do {
@@ -435,6 +437,14 @@ handle_fds(uint32_t next_interval)
     tvp.tv_sec = remaining / MSEC_PER_SEC;
     tvp.tv_usec = (remaining % MSEC_PER_SEC) * USEC_PER_MSEC;
   }
+
+  OLSR_FOR_ALL_SOCKETS(entry) {
+    if (entry->process_immediate == NULL && entry->process_pollrate == NULL) {
+      /* clean up socket handler */
+      list_remove(&entry->socket_node);
+      free(entry);
+    }
+  } OLSR_FOR_ALL_SOCKETS_END(entry);
 }
 
 /**
index 0b889db..394db96 100644 (file)
@@ -775,9 +775,7 @@ chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
 
   /* Register socket */
   add_olsr_socket(ifp->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
-  if (ifp->olsr_socket != ifp->send_socket) {
-    add_olsr_socket(ifp->send_socket, &olsr_input, NULL, NULL, SP_PR_READ);
-  }
+  add_olsr_socket(ifp->send_socket, &olsr_input, NULL, NULL, SP_PR_READ);
 
 #ifdef linux
   /* Set TOS */