> $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