Multisession blocking repair
authorBill Erickson <berick@esilibrary.com>
Fri, 15 Mar 2013 19:56:55 +0000 (15:56 -0400)
committerGalen Charlton <gmc@esilibrary.com>
Sun, 17 Mar 2013 18:42:34 +0000 (11:42 -0700)
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>
src/perl/lib/OpenSRF/MultiSession.pm

index e196027..4b9a996 100644 (file)
@@ -236,6 +236,20 @@ sub session_wait {
 }
 
 sub session_reap {
 }
 
 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;
        my $self = shift;
 
        my @done;