> $sock->timeout is intended to be a connect timeout. Why should read
> timeout be the same.

well, it seemed like a good compromise short of providing a new API, which
I didn't have any bright ideas about.  If you thought it best to provide
such an API, I wouldn't object to using it :)  Also, I guess I incorrectly
interpreted Net::LDAP's passing the timeout from new() to the underlying
socket and doing nothing else, as intending to do more than just implement
a connect timeout; e.g. at least one subsequent operation,
$ldap->start_tls(), inherits the same timeout.  I assumed there were other
such operations affected, maybe there are not.

>>>  my $sel = IO::Select->new($sock);
>>>  my $ready;
>>>
>>> -  for( $ready = 1 ; $ready ; $ready = $sel->can_read(0)) {
>>> +  for( $ready = 1 ; $ready ; $ready = $sel->can_read( $timeout )) {
>
> This would not be sufficient to stop the client hanging. ->process is
> called from within ->sync which will keep calling process until it gets
> the message response it is looking for.

The way I read that loop, as long as we can get can_read() to come back,
if the socket is not ready then it will behave the same as if the server
had dropped the connection - asn_read() will fail, causing process() to
return 'return _drop_conn($ldap, LDAP_OPERATIONS_ERROR, "Communications
Error")', which seems like a fairly appropriate error. If I'm reading it
wrong, then the effects of this change on our hanging-forever bug are odd
-- I can't imagine calling can_read($timeout) over and over again waiting
for it to come back would behave any differently than calling can_read(0),
and yet we did observe very different behavior to the effect of fixing our
bug.  Granted it could be that I managed to break things differently
rather than fix them :P

> Also if this message being waited on was the result of a call to, say,
> ->search. The callback for the search should be called with a client side
> error

>From my reading above I would think search() would return 'Communications
Error' as well.  I was not thorough enough in my testing to say this for
sure though.  I'd be willing to go back and test, if you felt this first
patch was conceptually a good idea at all.  If you'd rather see this done
with larger design and/or API changes, I don't know that I'd be your man.

>>> +  if ( $arg->{timeout} and IO::Socket->can('SO_SNDTIMEO') ) {
>>> +    my $timeval = pack 'L!L!', $ldap_opts->{timeout}, 0;
>>> +    eval {
>>> +      $obj->{net_ldap_socket}->sockopt( SO_SNDTIMEO, $timeval ) or die
>>> $!;
>>> +      $obj->{net_ldap_socket}->sockopt( SO_RCVTIMEO, $timeval ) or die
>>> $!;
>>> +    };
>
> Using low level socket options is almost never the right thing to be
> doing. using select or poll would be the right solution.

Fair enough... I admit this was a cheap shortcut to deal with the observed
shortcomings of the above patch, that is, it seems to enforce that any
single operation will time out in T seconds rather than T * N seconds

-Jared

Reply via email to