Improved workaround for stray events after handlers are deleted.

This really should never happen.  I traced through the code, and the only
way I can see it happening is if epoll returns an event after that fd is
unregistered... which is not supposed to be possible.  But maybe a kernel
bug could make it possible, or I've missed a case.

Anyway, when this happened and the respective handler had *already* been
removed and epoll had correctly already had the fd removed, we'd get an
uncaught exception when trying to remove it from epoll upon noticing that
there is no handler.

This changes the removal to use remove_handler() instead, which knows how to
catch the exception.  It also breaks out the KeyError check, just in case a
handler ever accidentally leaks an irrelevant KeyError that would cause
confusion.  (That doesn't seem to have actually happened so far.)

Also added a contrived unit test that at least fails with the old code and
passes with the new code.

b/17497758

Change-Id: Ic440d0251891e976eb0737d04a89dfed1b2678f6
diff --git a/tornado/ioloop.py b/tornado/ioloop.py
index 4189f58..a332100 100644
--- a/tornado/ioloop.py
+++ b/tornado/ioloop.py
@@ -325,7 +325,14 @@
             while self._events:
                 fd, events = self._events.popitem()
                 try:
-                    self._handlers[fd](fd, events)
+                    handler = self._handlers[fd]
+                except KeyError:
+                    logging.error("Handler for fd %s no longer exists, closing",
+                                  fd, exc_info=True)
+                    self.remove_handler(fd)
+                    continue
+                try:
+                    handler(fd, events)
                 except (OSError, IOError), e:
                     if e.args[0] == errno.EPIPE:
                         # Happens when the client closes the connection
@@ -333,10 +340,6 @@
                     else:
                         logging.error("Exception in I/O handler for fd %s",
                                       fd, exc_info=True)
-                except KeyError:
-                    logging.error("Handler for fd %s no longer exists, closing",
-                                  fd, exc_info=True)
-                    self._impl.unregister(fd)
                 except Exception:
                     logging.error("Exception in I/O handler for fd %s",
                                   fd, exc_info=True)