[Click] [PATCH] usermode Router::run_selects() not robust under handler deletion

Eddie Kohler kohler at icir.org
Fri Oct 31 15:08:57 EST 2003


Peter,

Thanks so much for this fix!! It's ridiculous: we knew this could happen,
at least when this comment got written:

   // Beware: calling 'selected()' might call remove_select(), causing
   // disaster! Load everything we need out of the vectors before calling
   // out.

Duh.

I've attached the patch I checked in. Note the different fix for your third
problem:

> I dropped the optimization in the 3rd fragment, in which self-deletion of
> handlers causes a re-scan of the new occupant of the slot. Nice trick,
> but it was also vulnerable to vector realloc problems if one of the handlers
> called add_select().
> The next poll() will catch the moved handler anyway.

I'm not sure I really understood the problem -- why not just fix up the 'p'
pointer, as attached?

Eddie

Index: lib/router.cc
===================================================================
RCS file: /home/am0/click/cvsroot/release/one/lib/router.cc,v
retrieving revision 1.149
diff -u -w -r1.149 router.cc
--- lib/router.cc	14 Oct 2003 18:47:03 -0000	1.149
+++ lib/router.cc	31 Oct 2003 23:03:47 -0000
@@ -1444,6 +1444,11 @@
       if (!p->events) {
 	*p = _pollfds.back();
 	_pollfds.pop_back();
+	// 31.Oct.2003 - Peter Swain: keep fds and elements in sync
+	_write_poll_elements[pi]  = _write_poll_elements.back();
+	_write_poll_elements.pop_back();
+	_read_poll_elements[pi]  = _read_poll_elements.back();
+	_read_poll_elements.pop_back();
 #if !HAVE_POLL_H
 	if (!_pollfds.size())
 	  _max_select_fd = -1;
@@ -1519,6 +1524,8 @@
 	if (write_elt >= 0 && write_elt != read_elt)
 	  _elements[write_elt]->selected(fd);
 
+	// 31.Oct.2003 - Peter Swain: _pollfds may have grown or shrunk!
+	p = _pollfds.begin() + pi;
 	if (p < _pollfds.end() && fd != p->fd)
 	  p--;
       }
@@ -1550,6 +1557,8 @@
 	if (write_elt >= 0 && write_elt != read_elt)
 	  _elements[write_elt]->selected(fd);
 
+	// 31.Oct.2003 - Peter Swain: _pollfds may have grown or shrunk!
+	p = _pollfds.begin() + pi;
 	if (p < _pollfds.end() && fd != p->fd)
 	  p--;
       }


More information about the click mailing list