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.
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 @@
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 @@
) where
import Control.Exception ( catch, throw )
+import Control.Monad ( when )
import Data.ByteString.Internal (c2w)
import Data.Functor
@@ -50,7 +51,13 @@
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