This is the mail archive of the
mailing list for the Cygwin project.
Re: python select() is limited to fds < 64
On 23/03/2011 20:14, Christopher Faylor wrote:
> On Wed, Mar 23, 2011 at 04:38:15PM +0000, Jon TURNEY wrote:
>> On 23/03/2011 15:00, Christopher Faylor wrote:
>>> On Wed, Mar 23, 2011 at 11:31:46AM +0000, Jon TURNEY wrote:
>>>> On 22/03/2011 20:08, Christopher Faylor wrote:
>>>>> On Tue, Mar 22, 2011 at 08:53:34PM +0100, V??clav Haisman wrote:
>>>>>> Jon TURNEY wrote, On 22.3.2011 20:29:
>>>>>>> python seems to be built with the default value of FD_SETSIZE, which is
>>>>>>> only 64 on cygwin.
>>>>>> Is this not because of the inherent limitation of
>>>>>> WaitForMultipleObjects() call?
>>>>> Yep. Without a rewrite, it's a hard limit to Cygwin's select().
>>>> Please read my email more closely. I am not saying "python select() is
>>>> limited to waiting on 64 fds or less", I am saying "python select() is
>>>> limited to waiting on fd which are less than 64"
>>> I forgot to add one bit of data. Unless you go out of your way to
>>> change it, Cygwin's select can't wait for an fd > 63. It's basically a
>>> bit mask. So, there are two limitations: 1) the number of handles that
>>> you can wait for with WaitForMultipleObjects() and 2) the size of
>>> Cygwin's fd_set.
>> Yes, I know fd_set is implemented as a bitmap. It's size is controlled by
>> FD_SETSIZE. That is the whole point of the patch in the original mail.
> I actually did see that last night and then promptly forgot it.
> I assume you know that this greately increases the likelihood that
> select() will fail with an EINVAL. Maybe python somehow deals
> gracefully with that.
Well, I believe if select() returns an error, python will raise an exception,
which is no less graceful than current behaviour.
I don't quite follow your reasoning that this change will increase the
likelihood of such exceptions, though.
To select() on more than 64 fds requires using fd numbers 64 and greater.
For existing python programs which use less than 64 fds, this change should
have no effect.
For existing python program which use more than 64 fds, at the moment they
will throw an exception on any attempt to use select() on fd number 64 or
greater. With this change, attempts to use select() on fd number 64 or
greater will succeed, provided fewer than 64 fds in total are selected on.
However... I did test my original patch, and didn't see an EINVAL error
occurring, which, now knowing that select() has this limitation, I should
have. So, another test case:
$ cat select_MAXIMUM_WAIT_OBJECTS_test.c
#define FD_SETSIZE 256
// gcc select_MAXIMUM_WAIT_OBJECTS_test.c -o select_MAXIMUM_WAIT_OBJECTS_test.exe
struct timeval t;
int i, n;
for (i = 0; i < FD_SETSIZE; i++)
int s = socket(AF_INET, SOCK_STREAM, 0);
printf("socket opened with fd %d\n", s);
t.tv_sec = 1;
t.tv_usec = 0;
n = select(FD_SETSIZE, &read, 0, 0, &t);
printf("select returned %d, errno %d\n", n, errno);
socket opened with fd 3
socket opened with fd 258
select returned 0, errno 0
Assuming this tests what I think it tests, EINVAL should be returned, but isn't.
Looking at select.cc in the cygwin source code, I can see that
select_stuff::wait() has code to return EINVAL if we exceed
MAXIMUM_WAIT_OBJECTS, so this puzzled me for a while.
Looking at this in a bit more detail, it seems that start_thread_socket()
guzzles all the sockets and starts a single thread, the handle of which it
returns to wait() to WMFO on for every socket fd, even though thread_socket()
will only wait on MAXIMUM_WAIT_OBJECTS at most.
I guess I need to write a patch for this problem, also :-)
Problem reports: http://cygwin.com/problems.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple