While trying to track down a problem with our application (http://allmydata.org) running under cygwin, I discovered that the select.poll() object sometimes returns completely bogus data. poll() returns a list of tuples of (fd, revent), but fds are supposed to be small integers, and revents are a bitmask of POLLIN/POLLOUT flags. In my tests, I saw poll() return a list that started out looking normal, but the last half of the list contained fds and revents values like fd=0x7672a646, revent=0xd819.
It turns out that under cygwin-1.5.24 (which I believe is a pretty recent version), the poll() call sometimes violates the POSIX specification, and provides a return value which is different than the number of pollfd structures that have non-zero .revents fields (generally larger). This causes the implementation of poll_poll() (in Modules/selectmodule.c) to read beyond the end of the pollfd array, copying random memory into the python list it is building, causing the bogus values I observed during my tests.
These bogus values were mostly ignored, because the Twisted pollreactor that I was using noticed that the fd didn't correspond to any previously-registered file descriptor. It was only when the bogus fd happened to coincide with a real one (and when that indicated that a TCP listening socket became writable, which should never happen) that an exception was raised.
The attached patch (against 2.5.1) works around the problem by manually counting the number of non-zero .revents, rather than relying upon the return value from poll(). This version passes test_poll on both linux and cygwin.
cheers,
-Brian Warner
|