[Python-Dev] Non-blocking sockets, asynchronous connects and select.select.

2007-03-19 Thread Alan Kennedy
Dear all,

I'm working on a select implementation for jython (in combination with
non-blocking sockets), and a set of unit tests for same.

I decided to run all of the non-blocking unit tests, both server and
client side, in the same thread; seems to be a reasonable thing to do.
After all, avoiding threads is one of the great benefits of
non-blocking sockets.

Also, I'm writing the tests so that they'll hopefully pass on both
cpython and jython.

But I'm getting behaviour I don't expect on cpython, when a
non-blocking accept and connect_ex is used, for the server and client
sides respectively.

The following piece of code outputs what I expect on my jython
implementation, which is that both the server accept and client write
calls would NOT block.

But when I run the code on cpython, the code reports that both calls
would block, i.e. that neither side of the socket will progress with
the connection.

The code is

# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
import socket
import select

SERVER_ADDRESS = ("", 54321)

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setblocking(0)
server_socket.bind(SERVER_ADDRESS)
server_socket.listen(5)

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.setblocking(0)

result = client_socket.connect_ex(SERVER_ADDRESS)

rfds, wfds, xfds = select.select([server_socket], [client_socket], [], 1)
if server_socket in rfds:
print "Server socket: accept would not block"
else:
print "Server socket: accept would block"
if client_socket in wfds:
print "Client socket: write would not block"
else:
print "Client socket: write would block"

server_socket.close()
client_socket.close()
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Is there some call that I am missing, e.g. something along the lines
of the java finishConnect() method on SocketChannel?

http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/SocketChannel.html#finishConnect()

Is there any way to make the above code report, on cpython, that
neither side of the socket would block?

Am I missing some essential method call that would make either side
progress to a connected socket?

Thanks,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Non-blocking sockets, asynchronous connects and select.select.

2007-03-20 Thread Alan Kennedy
Thanks Josiah and Neal, you were right.

I am running the code on Windows, Server 2003. I should have mentioned
that at the start.

When I change the hostname from "" to "localhost", the code works
exactly as expected.

It's odd that this behaviour exists, only on Windows.

The jython code that I'm writing worked fine with an empty hostname
"". That jython code uses the java.net and java.nio APIs directly, and
does not have any special cases for empty hostname.

Which must mean that the underlying java implementations must be
correctly handling the empty hostname, even when running on Windows.
(Perhaps by special casing for the Windows implementation, if indeed a
peculiarity of the Windows socket libraries is the cause).

Which implies to me that cpython, like java, should not have different
behaviour on Windows vs. other platforms; it lessens portability. Lack
of portability is confirmed by Neal's report that the original
unmodified snippet (i.e. with hostname == "") works correctly under
cpython on Linux.

Thanks guys,

Alan.


On 3/20/07, Josiah Carlson <[EMAIL PROTECTED]> wrote:
> [snip]
> > SERVER_ADDRESS = ("", 54321)
>
> Replacing the above with:
>
>SERVER_ADDRESS = ("localhost", 54321)
>
> ...makes it work for me on Windows CPython 2.3.5 and 2.5 .
>
>  - Josiah
>
>
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-20 Thread Alan Kennedy
[Facundo Batista]
> Do you have any news about this?

Re: Patch 1676823
http://sourceforge.net/tracker/index.php?func=detail&aid=1676823&group_id=5470&atid=305470

Since I've just written a lot of socket stuff for jython, I thought
I'd have a look at the patch.

I like the idea of adding better socket control to the higher-level
modules like httplib, etc, because these modules don't provide access
to the underlying sockets, and using the socket module methods
setdefaulttimeout, etc, is a little messy.

I see that your updated socket.connect() method takes a timeout
parameter, which defaults to None if not present, e.g.

def connect(address, timeout=None):

Later in the function, this line appears

if timeout is not None:
  sock.settimeout(timeout)

The problem with this is that None has a meaning as a timeout value;
it means "put this socket in blocking mode". But that value can no
longer be used for socket connects, since that value is being
interpreted as "parameter was not provided".

So, if a non-standard timeout has been set, using something like

import socket ; socket.setdefaulttimeout(10.0)

how do I restore full blocking behaviour to a single socket? (a
somewhat contrived case, I admit).

If I have access to the socket object, then I can call
"sock_obj.settimeout(None)", but in that case I don't need the new
API. I could also do it with the call "sock_obj.setblocking(1)".

If I don't have access to the socket object, i.e. I'm using timeouts
indirectly through httplib/etc, then I'm stuck: there's no way I can
change the blocking or timeout behaviour; back to square one.

So the new proposed API partly addresses the problem of increasing
control over the underlying socket, but doesn't address all cases. It
specifically prevents setting a timeout value of None on a socket,
which is an important use case, I think.

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-20 Thread Alan Kennedy
[Alan Kennedy]
>> I see that your updated socket.connect() method takes a timeout
>> parameter, which defaults to None if not present, e.g.

[Facundo Batista]
> I did NOT update a connect() method. I created a connect() function, in
> the module socket.py (there's also a connect() method in the socket
> object, but I didn't touch it).

Sorry, my mistake.

I realise now that you're creating a whole new function, dedicated to
the special (but extremely common) case of creating a fully connected
client socket. My fault for not realising that first off.

So, a question I would ask is: Is "connect" the right name for that function?
 - Will users get confused between the "connect" function and
socket.connect method? They are doing different things.
 - Will the naming give rise to the question "the socket-module-level
function connect() takes a timeout parameter, why doesn't the
socket-method connect() take a timeout parameter as well?"

Perhaps a better name might be "create_connected_client_socket", or
something equally descriptive?

Another question I would ask is: "How do I ensure that my newly
created connected client socket is in blocking mode, *without* making
any assumptions about the value of socket.getdefaulttimeout()?"

If the answer to this question is "you can't", then I would suggest a
function signature and implementation like this instead

def connect(address, **kwargs):
[snip]
if kwargs.has_key('timeout'):
sock.settimeout(kwargs['timeout'])
[snip]

This would of course mean that the user would have to explicitly name
the 'timeout' parameter, but that's a good thing in this case, IMO.

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-20 Thread Alan Kennedy
[Facundo]
> But, I recognize that maybe it's [connect] not the best name. What about
> "create_connection"?

I have no strong feelings about it, other than to say it should not be
"connect". How about

 * connect_to_server()
 * open_connection()
 * open_client_connection()

There's no need to include "timeout" in the name, IMO.

[Alan]
>> Another question I would ask is: "How do I ensure that my newly
>> created connected client socket is in blocking mode, *without* making
>> any assumptions about the value of socket.getdefaulttimeout()?"

[Facundo]
> Call like this:
>
>  newsock = socket.connect((..., ...))
>  newsock.setblocking(1)

Ah, but it's too late by the time the socket.connect call returns: the
timeout/blocking behaviour of the socket.connect call is the very
thing we're trying to control.

Whenever I look at the proposed API, I think: What happens when the
socket.connect call is preceded by a call which changes the default
socket timeout/blocking behaviour, e.g.

socket.setdefaulttimeout(1)
newsock = socket.connect(HOST, PORT, None) # <-- None param ignored
newsock.setblocking(1) # <-- This does not affect the behaviour of the connect

I.E. I do not get the blocking behaviour I want. The proposed API does
not permit me to get blocking behaviour by specifying a timeout value
of None.

Whereas with the slightly modified API I suggested earlier, it simply becomes

socket.setdefaulttimeout(1)
newsock = socket.connect(HOST, PORT, timeout=None)
# newsock.setblocking(1) # <-- No longer relevant

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-20 Thread Alan Kennedy
[Facundo]
> So, I have two modifications to make to the patch:
>
> - change the name to "create_connection"
> - make timeout obligatory named

I was going to suggest a third change: for orthogonality with the API
for socket objects, add a blocking parameter as well, i.e.

def create_connection(address, timeout=sentinel, blocking=sentinel):
  [snip]
if timeout != sentinel:
  new_socket.settimeout(timeout)
if blocking != sentinel:
  new_socket.setblocking(blocking)
  [snip]

but that may be taking it too far.

But there is still an issue remaining, relating to non-blocking IO.

With or without a blocking parameter, the user can still set
non-blocking behaviour on a socket by setting a timeout of 0. The
following snippet illustrates the issue.

#-=-=-=-=-=-=-=-=-=-=-=-=-=
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0)
s.connect( ("localhost", 80) )
#-=-=-=-=-=-=-=-=-=-=-=-=-=

If you run this, it is very likely to generate an exception, but not
guaranteed: you may have to run it a few times. Or try a host that is
slower to respond.

The problem is now that the connect call is now a non-blocking
connect, which means that it may throw a socket.error, even after a
successful connect, as follows

socket.error: (10035, 'The socket operation could not complete without
blocking')

The standard mechanism in C for doing a non-blocking connect is to
issue the connect call, and check the return value for a non-zero
error code. If this error code is errno.EAGAIN (code 10035), then the
call succeeded, but you should check back later for completion of the
operation.

It was for this reason that the connect_ex method was introduced to
python socket objects. Instead of raising an exception, it directly
returns the error code from the socket operation, so that it can be
checked, as in C.

So in the case of the new create_connection function, either

A: The user should be prepared to handle an exception if they use a
zero timeout (i.e. set non-blocking mode)

or

B: Detect the non-blocking case inside the function implementation and
return the value of the connect_ex method instead of the connect
method, as would be standard in a non-blocking app.

This could be implemented as follows

def create_connection(address, timeout=sentinel):
  [snip]
 if timeout != sentinel:
   new_socket.settimeout(timeout)
 if new_socket.gettimeout() == 0:
   result = new_socket.connect_ex(address)
 else:
   new_socket.connect(address)
   result = new_socket
  [snip]

I know that this makes it all more complex, and I'm *not* saying the
new function should be modified to include these concerns.

The new function is designed to address straightforward usability
cases, so it's perhaps appropriate that the API be restricted to those
cases, i.e. to supporting timeout values > 0. Perhaps this limit could
be coded into the function?

Also, people who want explicitly do non-blocking socket IO will likely
use the socket API directly, so it may not be worth supporting that
use in this function.

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-20 Thread Alan Kennedy
[Josiah]
> But now the result could be either an error code OR a socket.  One of
> the reasons to provide a timeout for the create_connection call, if I
> understand correctly, is to handle cases for which you don't get a
> response back in sufficient time.

AFAICT, that's the only reason. It's not to handle blocking sockets,
that's the default operation of sockets. And it's not to handle
non-blocking sockets either.

>If the user provides zero as a
> timeout, then they may very well get an exception, which is what they
> should expect.

Yes, they should expect it. And they would handle it like this

try:
  new_socket = socket.create_connection(address, 0):
except socket.error:
  import errno:
  if errno.errno == 10035 # or relevant platform specific symbolic constant
# socket is still connecting
  else:
# there was a real socket error

> Then again, even with an arbitrary timeout, an exception
> is possible (especially if a host is down, etc.), and hiding the
> exceptional condition (didn't connect in the allotted time) is a bad
> thing.

See above.

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-20 Thread Alan Kennedy
[Facundo]
> Letting "timeout" be positional or named, it's just less error prone.
> So, if I can make it this way, it's what I prefer, :)

So, if I want a timeout of, say, 80 seconds, I issue a call like this

new_socket = socket.create_connection(address, 80)

So is that address = host, port = 80?

Or is it address = (host, port), timeout=80?

I know *we* know what it is, but will the user?

I prefer explicit naming of the timeout parameter.

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-20 Thread Alan Kennedy
[Josiah]
> Error-wise, I agree that it would be better to pass timeout explicitly
> with a keyword, but generally users will notice their mistake if they
> try to do create_connection(host, port) by ValueError("tuple expected as
> first argument, got str instead") Is it better than
> TypeError("create_connection takes 1 argument (2 given)") ?

Yes, it is better.

Currently, the socket.connect() method takes a tuple, and fails with
the following exception if 2 separate parameters are passed

TypeError: connect() takes exactly one argument (2 given)

Which is fine because the function does take exactly one argument. But
we're discussing a function with an optional timeout parameter, so
that TypeError wouldn't be raised if I called
create_connection("localhost", 80).

The patch as it currently is, if I am reading it right, would raise
one of the following if a string was passed as the address argument,
depending on the length of the string.

ValueError: need more than 1 value to unpack # len(address) == 1
ValueError: too many values to unpack   # len(address) > 2

since it extracts the host and port like so

host, port = address

Which succeeds, somewhat surprisingly, if a string is passed that is 2
characters long. I was a little surprised to find that this didn't
give rise to an error: host, port = "ab".

So with a two character hostname, the second letter would be unpacked
as a port number.  And the function would then fail with the following
exception when it reaches the getaddrinfo ("a", "b", 0, SOCK_STREAM)
call.

socket.gaierror: (10109, 'getaddrinfo failed')

I suggest updating the patch to

 - Explicitly check that the address passed is a tuple of (string, integer)
 - To raise an exception explaining the parameter expectation when it is not met
 - To require that the user explicitly name the timeout parameter

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] I vote to reject: Adding timeout to socket.py and httplib.py.

2007-03-21 Thread Alan Kennedy
[Facundo Batista]
> Remember that this function primary use is for
> higher level libraries

Yes, I see that clearly now.

But remember that by adding a new function to the socket module to
support httplib et al, you are also adding a function to the socket
module that will be used directly by end users.

I vote to reject this patch.

The underlying problem it is trying to address is that
httplib.HTTPConnection objects do not support timeouts.

But solving that problem by moving the functionality of the
HTTPConnection.connect() method inside the socket module as a
standalone function is the *wrong* solution.

The proposed new function does not belong in the socket module. In
contrast to all of the other socket creation and management
functionality in the socket module, the new function does not handle
non-blocking IO.

Also, the new functions' use-case is too restricted, to client
connections with a positive timeout: this functionality is trivially
available using existing functionality, e.g.

mysock = socket(AF_INET, SOCK_STREAM)
mysocket.settimeout(1.0)
mysocket.connect( (host, port) )
# etc

In contrast to the new function, the existing functionality in the
socket module is much more general, and much better designed to handle
the wide range of situations in which sockets are used. Socket APIs
are hard to do right because sockets are complex and hard to do right.

The problem the patch seeks to fix is is in httplib; the problem
should be fixed in httplib.

I recommend modifying the patch to remove *all* proposed changes to
the socket module. Instead, the patch should restrict itself to fixing
the httplib module.

Sorry,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] I vote to reject: Adding timeout to socket.py and httplib.py.

2007-03-21 Thread Alan Kennedy
[Facundo]
> Voting is open, ;)

So what are we voting on exactly? The patch as it currently is? The
patch has not been updated to reflect recent discussions on the list.
Will the patch be updated before the vote?

I have one more issue with the patch.

I think that the exception handling in the function is wrong. This is
(approximately) the way the patch is currently defined.

def create_connection(address, **kwargs):
 msg = "getaddrinfo returns an empty list"
 host, port = address
 for res in getaddrinfo(host, port, 0, SOCK_STREAM):
 af, socktype, proto, canonname, sa = res
 sock = None
 try:
 [snip]
 return socket
 except error, err:
 msg = str(err) # <-- don't do this
 if sock is not None:
 sock.close()
 raise error(msg)

Changing the exception to with msg = str(err) is the wrong thing to
do: this will hide the exception and make comparisons with symbolic
constants fail, for users that want to handle exceptions.

The correct way to handle

1. An empty return from getaddrinfo()
2. Other socket errors

is as follows

def create_connection(address, **kwargs):
host, port = address
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
[snip]
return new_socket
except error, err:
if sock is not None:
sock.close()
raise err
else:
raise error("getaddrinfo returns an empty list")

[Facundo]
> Or it's just denial towards this patch?

I think this patch is poorly designed and poorly implemented. There
are multiple problems in its 17 lines of socket module code; every
time I look I find a new problem.

Sorry.

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] I vote to reject: Adding timeout to socket.py and httplib.py.

2007-03-21 Thread Alan Kennedy
[Facundo]
> Talk is cheap.

I'm sorry if you see my attempts to review your patch as "cheap talk".
Maybe I should have just kept my opinion to myself.

You'll get your chance to return the favour when I check in my
upcoming 1000+ line change to jython 2.3 to bring the jython socket,
select and asyncore modules up-to-date with cpython 2.5, including
providing ssl support, non-blocking IO, select/poll, etc, for the
first time in jython.


Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] I vote to reject: Adding timeout to socket.py and httplib.py.

2007-03-21 Thread Alan Kennedy
[Facundo]
> Talk is cheap.

I'm sorry if you see my attempts to review your patch as "cheap talk".
Maybe I should have just kept my opinion to myself.

You'll get your chance to return the favour when I check in my
upcoming 1000+ line change to jython 2.3 to bring the jython socket,
select and asyncore modules up-to-date with cpython 2.5, including
providing ssl support, non-blocking IO, select/poll, etc, for the
first time in jython.


Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] I vote to reject: Adding timeout to socket.py and httplib.py.

2007-03-21 Thread Alan Kennedy
[Josiah]
> In regards to 'there is no way to
> create a blocking socket this way', Alan is off his rocker.

I am not off my rocker.

And I never wrote the words you place in quotes (except in relation to
an earlier defect in the patch where the timeout=None value was
ignored).

What I clearly stated is that the function as is doesn't cater for
*non-blocking* sockets. I also clearly stated that I have no problem
with the fact that it doesn't handle non-blocking sockets, but this
either

A: Needs to be enforced in the function by disallowing zero timeouts
B: Needs to be recorded in the documentation

The use cases for the function are limited: that's fine. But either
explicitly limit them or document those limits.

> The function is needed, and the implementation is sufficient for its
> intended uses.

When all the defects are fixed, it will be sufficient.

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] I vote to reject: Adding timeout to socket.py and httplib.py.

2007-03-21 Thread Alan Kennedy
[Greg Ewing]
> or
>
>  d) Put it in another module
>
> Is it time for a sockettools module, maybe?

+1!

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] I vote to reject: Adding timeout to socket.py and httplib.py.

2007-03-21 Thread Alan Kennedy
[Facundo]
> Talk is cheap.

I'm sorry if you see my attempts to review your patch as "cheap talk".
Maybe I should have just kept my opinion to myself.

You'll get your chance to return the favour when I check in my
upcoming 1000+ line change to jython 2.3 to bring the jython socket,
select and asyncore modules up-to-date with cpython 2.5, including
providing ssl support, non-blocking IO, select/poll, etc, for the
first time in jython.

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Adding timeout to socket.py and httplib.py

2007-03-22 Thread Alan Kennedy
[Alan]
>> - Explicitly check that the address passed is a tuple of (string, integer)

[Facundo]
> In the code, I'll just make "host, port = address", I don't think it
> will be a problem at all. Remember that this function primary use is for
> higher level libraries, and that "address" in socket enviroment is
> always, always, (host, port).

It's rather unfortunate that the tuple needs to be unpacked at all.

Instead, it should be possible to simply pass the address tuple
directly to the socsket.getaddrinfo() function, and let it worry about
the tuple-ness of the address, raising exceptions accordingly.

The socket.getaddrinfo() function, unlike every other python socket
function, takes separate host and port parameters. Which forces every
user of the socket.getaddrinfo function to do the same unnecessary and
potentially error-prone address tuple unpacking.

I have raised a feature request to change this.

[1685962] socket.getaddrinfo() should take an address tuple.

Regards,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Return value from socket.fileno()

2007-05-23 Thread Alan Kennedy
Dear all,

I am writing to seek information about the socket.fileno() method, and 
opinions on how best to implement it on jython.

On cpython, socket.fileno() returns a file descriptor, i.e. an integer 
index into an array of file objects. This integer is then passed to 
select.select and select.poll, to register interest in specified events 
on the socket, i.e. readability, writability, connectedness, etc.

Importantly, it is possible to select and poll on a socket's file 
descriptor immediately after the socket is created, e.g. before it is 
connected and even before a non-blocking connect process has been started.

This is problematic on java, because java has different classes for 
client and server sockets. Therefore, on jython, creation of the actual 
socket implementation is deferred until the user has called a method 
which commits the socket to being a client or server socket, e.g. 
connect, listen, etc. This means that there is no meaningful 
descriptor/channel that can be returned from fileno() until the nature 
of the socket is determined.

Also, file descriptors have no meaning on java. Instead, java Selectors 
select on java.nio.channels.SelectableChannel objects. But, ideally, 
this should not matter: AFAICT, the return value from fileno should be 
simply an opaque handle which has no purpose other than to be handed to 
select and poll, to indicate interest in events on the associated socket.

I have been thinking that the simplest way to implement socket.fileno() 
on jython is to return the actual socket object, i.e. return self. When 
this object is passed to select/poll as a parameter, the select/poll 
implementation would know to retrieve the underlying java 
SelectableChannel, if it exists yet. If it does not yet exist, because 
the socket is not yet commited to being a server or client socket, then 
it is simply excluded from the select/poll operation.

The only problem with it is returning a non-integer from the fileno() 
method; instead a socket object would be returned.

So the question I'm asking is: Does anyone know of existing cpython code 
which relies on the return value from socket.fileno() being an integer? 
Or code that would break if it were returned a socket instance instead 
of an integer?

Thanks,

Alan.

P.S. If anyone is interested, a non-blocking sockets and select (and 
soon asyncore) implementation is currently residing in the jython 
sandbox. It is hoped that it will be included in jython 2.2rc1. More here

http://wiki.python.org/jython/NewSocketModule
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Return error codes from getaddrinfo.

2007-06-27 Thread Alan Kennedy
Dear all,

I'm seeking enlightenment on the error codes returned by the 
socket.getaddrinfo() function.

Consider the following on python 2.5 on Windows

 >>> import urllib
 >>> urllib.urlopen("http://nonexistent";)
  [snip traceback]
IOError: [Errno socket error] (11001, 'getaddrinfo failed')

So the error number is 11001.

But when I try to find a symbolic constant in the errno module 
corresponding to this error number, I can't find one.

 >>> import errno
 >>> errno.errorcode[11]
'EAGAIN'
 >>> errno.errorcode[11001]
Traceback (most recent call last):
   File "", line 1, in 
KeyError: 11001

Looking through the C source for the socket module doesn't provide any 
clarity (although my C is a little rusty). That module has a special 
function, set_gaierror(), for handling error returns from getaddrinfo. 
But I can't see if or how the resulting error codes relate to the errno 
module.

Is there supposed to be symbolic constants in the errno module 
corresponding to getaddrinfo errors?

I want jython to use the same errno symbolic constants as cpython, to 
ease portability of code.

Regards,

Alan.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Return error codes from getaddrinfo.

2007-06-28 Thread Alan Kennedy
[Alan]
>>I want jython to use the same errno symbolic constants as cpython, to 
>>ease portability of code.

[Martin]
> That will be very difficult to achieve, as Python is (deliberately)
> not even consistent across systems. Instead, it reports what the
> platform reports, so you should do the same in Java.

I think I need to explain myself more clearly; I'm looking for the 
errno.SYMBOLIC_CONSTANT for errors returned by the getaddrinfo function.

Take the following lines from the cpython 2.5 httplib.

Line 998 - 1014
# -=-=-=-=-=-=
while True:
 try:
 buf = self._ssl.read(self._bufsize)
 except socket.sslerror, err:
 if (err[0] == socket.SSL_ERROR_WANT_READ
 or err[0] == socket.SSL_ERROR_WANT_WRITE):
 continue
 if (err[0] == socket.SSL_ERROR_ZERO_RETURN
 or err[0] == socket.SSL_ERROR_EOF):
 break
 raise
 except socket.error, err:
 if err[0] == errno.EINTR:
 continue
 if err[0] == errno.EBADF:
 # XXX socket was closed?
 break
 raise
# -=-=-=-=-=-=-=

How can that code work on jython, other than if

A: The jython errno module contains definitions for EINTR and EBADF
B: The socket module raises the exceptions with the correct 
errno.SYMBOLIC_CONSTANTS, in the same circumstances as the cpython module.

(The actual integers don't matter, but thanks anyway to the three 
separate people who informed me that googling "11001" was the solution 
to my problem).

And then there are the non-portable uses of error numbers, like this 
snippet from the 2.5 httplib:

Lines 706-711
#-=-=-=-=-=-=
 try:
 self.sock.sendall(str)
 except socket.error, v:
 if v[0] == 32:  # Broken pipe
 self.close()
 raise
#-=-=-=-=-=-=

Do these examples make it clearer why and in what way I want the jython 
errno symbolic constants to be the same as cpython?

Thanks,

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] httplib &c. timeouts and global state

2008-03-26 Thread Alan Kennedy
[This message will not be threaded properly since I wasn't subscribed
at the time the original was sent]

[John]
> What I found in the archive is this thread (sorry for the
> non-python.org URL):
>
> http://www.gossamer-threads.com/lists/python/dev/555039?do=post_view_threaded#555039
>
> In that discussion, this issue is raised, but I don't see any resolution
> that answers the objection made in issue 2451.  Anyway, apologies in
> advance if there was a decision here that takes account of the above
> objection.

The solution to the problem John descibes WAS decided back at the time
of discussion of the contribution, but for some reason, that solution
never made into contribution that was committed.

http://www.gossamer-threads.com/lists/python/dev/555108?do=post_view_threaded#555108
http://www.gossamer-threads.com/lists/python/dev/555110?do=post_view_threaded#555110

The solution is simple, as described on the bug that John created for
this issue.

http://bugs.python.org/issue2451

Alan.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com