The new socket blocking code for multisession failed to take into
account that socket activity outside of the main block could lead to a
deadlock situation. For example:
* Check status of request A -> not complete
* Check status of request B -> whatever
* Request A may now be complete, since checking the status of any request
affects all requests
* Return to blocking loop because we think there is pending data, but in
fact all data has already been pulled from the socket.
The solution is for session_reap() to make a sweep and check for changes
in requests that are now complete as a side-effect of checking for
completed requests.
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Galen Charlton <gmc@esilibrary.com>
}
sub session_reap {
+ my $self = shift;
+ $self->_session_reap;
+
+ # if any requests are marked complete as a side effect of
+ # _session_reap, re-run _session_reap. note that we check
+ # for completeness without touching the underlying socket
+ # (req->{complete} vs req->complete) to avoid additional
+ # unintended socket-touching side effects.
+ while (grep { $_->{req}->{complete} } @{$self->{running}}) {
+ $self->_session_reap;
+ }
+}
+
+sub _session_reap {
my $self = shift;
my @done;