This is an automated email from the ASF dual-hosted git repository.

jensg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/thrift.git


The following commit(s) were added to refs/heads/master by this push:
     new 261de34  THRIFT-5211 Handle incomplete reads correctly Client: Haskell 
Patch: Philipp Hausmann
261de34 is described below

commit 261de348fe0e83ca2f4c7398f2f03ff28d3eb81e
Author: Philipp Hausmann <[email protected]>
AuthorDate: Wed Apr 22 16:20:46 2020 +0200

    THRIFT-5211 Handle incomplete reads correctly
    Client: Haskell
    Patch: Philipp Hausmann
    
    This closes #2108
    
    The read functions for handles promise to return *up* to the requested
    number of bytes. This means in case we read less bytes, we should try
    again to read some more bytes.
---
 lib/hs/src/Thrift/Transport/Framed.hs | 4 ++--
 lib/hs/src/Thrift/Transport/Handle.hs | 9 ++++++++-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/lib/hs/src/Thrift/Transport/Framed.hs 
b/lib/hs/src/Thrift/Transport/Framed.hs
index 42fc43f..ad553ae 100644
--- a/lib/hs/src/Thrift/Transport/Framed.hs
+++ b/lib/hs/src/Thrift/Transport/Framed.hs
@@ -87,11 +87,11 @@ instance Transport t => Transport (FramedTransport t) where
 readFrame :: Transport t => FramedTransport t -> IO Int
 readFrame trans = do
   -- Read and decode the frame size.
-  szBs <- tRead (wrappedTrans trans) 4
+  szBs <- tReadAll (wrappedTrans trans) 4
   let sz = fromIntegral (B.decode szBs :: Int32)
 
   -- Read the frame and stuff it into the read buffer.
-  bs <- tRead (wrappedTrans trans) sz
+  bs <- tReadAll (wrappedTrans trans) sz
   fillBuf (readBuffer trans) bs
 
   -- Return the frame size so that the caller knows whether to expect
diff --git a/lib/hs/src/Thrift/Transport/Handle.hs 
b/lib/hs/src/Thrift/Transport/Handle.hs
index ff6295b..528a027 100644
--- a/lib/hs/src/Thrift/Transport/Handle.hs
+++ b/lib/hs/src/Thrift/Transport/Handle.hs
@@ -28,6 +28,7 @@ module Thrift.Transport.Handle
     ) where
 
 import Control.Exception ( catch, throw )
+import Control.Monad ( when )
 import Data.ByteString.Internal (c2w)
 import Data.Functor
 
@@ -50,7 +51,13 @@ instance Transport Handle where
           hLookAhead h
           LBS.hGetNonBlocking h n
     tReadAll _ 0 = return mempty
-    tReadAll h n = LBS.hGet h n `Control.Exception.catch` throwTransportExn
+    tReadAll h n = do
+      result <- LBS.hGet h n `Control.Exception.catch` throwTransportExn
+      let rlen = fromIntegral $ LBS.length result
+      when (rlen == 0) (throw $ TransportExn "Cannot read. Remote side has 
closed." TE_UNKNOWN)
+      if n <= rlen
+        then return result
+        else (result `mappend`) <$> tReadAll h (n - rlen)
     tPeek h = (Just . c2w <$> hLookAhead h) `Control.Exception.catch` 
handleEOF Nothing
     tWrite = LBS.hPut
     tFlush = hFlush

Reply via email to