packages feed

pqi-native 1.0.1.1 → 1.0.1.2

raw patch · 3 files changed

+18/−3 lines, 3 filesdep ~pqi-conformancePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: pqi-conformance

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+# v1.0.1.2++## Fixes++- Fixed an async exception (e.g. from `System.Timeout.timeout`) landing mid-read permanently desyncing a connection's message framing. `Transport.receiveFrame` now runs `uninterruptibleMask_`ed, so a frame is either read to completion or not started, mirroring how `pqi-ffi`'s `safe` FFI call into `libpq` is structurally immune to the same hazard. Caught by the differential coverage in `pqi-conformance` 1.0.3.0 (#5).+ # v1.0.1.1  ## Fixes
pqi-native.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: pqi-native-version: 1.0.1.1+version: 1.0.1.2 category: Database, PostgreSQL synopsis: Native (pure-Haskell) adapter for pqi description:@@ -158,5 +158,5 @@   build-depends:     base >=4.11 && <5,     hspec >=2.11 && <2.12,-    pqi-conformance ^>=1.0.2.0,+    pqi-conformance ^>=1.0.3.0,     pqi-native,
src/transport/Pqi/Native/Transport.hs view
@@ -14,6 +14,7 @@   ) where +import Control.Exception (uninterruptibleMask_) import qualified Data.ByteString as ByteString import qualified Data.ByteString.Char8 as ByteString.Char8 import Data.IORef@@ -83,8 +84,16 @@  -- | Receive one framed message: its type byte and its body (the length prefix, -- which counts itself, is consumed).+--+-- Runs fully 'uninterruptibleMask_'ed: 'Socket.ByteString.recv' is+-- interruptible even under a plain 'mask', so an async exception (e.g. from+-- 'System.Timeout.timeout') landing between a @recv@ returning and its bytes+-- being folded into 'readBuffer' would otherwise drop them - desyncing the+-- connection's framing for every subsequent read. Deferring delivery across+-- the whole frame mirrors how @pqi-ffi@'s @safe@ FFI call into @libpq@ is+-- immune to the same hazard. receiveFrame :: Transport -> IO (Word8, ByteString)-receiveFrame transport = do+receiveFrame transport = uninterruptibleMask_ do   header <- receiveExactly transport 5   let typeByte = ByteString.head header       frameLength = decodeInt32BE (ByteString.drop 1 header)