network 2.7.0.1 → 2.7.0.2
raw patch · 8 files changed
+86/−14 lines, 8 filesdep ~base
Dependency ranges changed: base
Files
- CHANGELOG.md +12/−0
- Network/Socket.hsc +41/−10
- Network/Socket/ByteString/Lazy/Posix.hs +3/−0
- Network/Socket/ByteString/Lazy/Windows.hs +3/−0
- Network/Socket/Types.hsc +15/−0
- configure.ac +1/−1
- network.cabal +3/−3
- tests/SimpleSpec.hs +8/−0
CHANGELOG.md view
@@ -1,3 +1,15 @@+## Version 2.7.0.2++* Removing withMVar to avoid the deadlock between "accept" and "close"+ [#330](https://github.com/haskell/network/pull/330)+* "close" does not throw exceptions. A new API: "close'" throws+ exceptions when necessary.+ [#337](https://github.com/haskell/network/pull/337)+* Fixing the hang of lazy sendAll.+ [#340](https://github.com/haskell/network/pull/340)+* Installing NetDef.h (#334)+ [#334](https://github.com/haskell/network/pull/334)+ ## Version 2.7.0.1 * A new API: socketPortSafe.
Network/Socket.hsc view
@@ -88,6 +88,12 @@ -- > msg <- recv sock 1024 -- > putStr "Received: " -- > C.putStrLn msg+--+-- The proper programming model is that one 'Socket' is handled by+-- a single thread. If multiple threads use one 'Socket' concurrently,+-- unexpected things would happen. There is one exception for multiple+-- threads vs a single 'Socket': one thread reads data from a 'Socket'+-- only and the other thread writes data to the 'Socket' only. ----------------------------------------------------------------------------- #include "HsNet.h"@@ -114,6 +120,7 @@ , accept -- ** Closing , close+ , close' , shutdown , ShutdownCmd(..) -- * Socket options@@ -623,7 +630,8 @@ -> IO (Socket, -- Readable Socket SockAddr) -- Peer details -accept sock@(MkSocket s family stype protocol status) = withMVar status $ \currentStatus -> do+accept sock@(MkSocket s family stype protocol status) = do+ currentStatus <- readMVar status if not $ isAcceptable family stype currentStatus then ioError $ userError $@@ -1295,17 +1303,40 @@ -- ----------------------------------------------------------------------------- --- | Close the socket. Sending data to or receiving data from closed socket--- may lead to undefined behaviour.+-- | Close the socket. This function does not throw exceptions even if+-- the underlying system call returns errors.+--+-- Sending data to or receiving data from closed socket+-- may lead to undefined behaviour.+--+-- If multiple threads use the same socket and one uses 'fdSocket' and+-- the other use 'close', unexpected behavior may happen.+-- For more information, please refer to the documentation of 'fdSocket'. close :: Socket -> IO ()-close (MkSocket s _ _ _ socketStatus) = do- modifyMVar_ socketStatus $ \ status ->+close (MkSocket s _ _ _ socketStatus) = modifyMVar_ socketStatus $ \ status -> case status of- ConvertedToHandle ->- ioError (userError ("close: converted to a Handle, use hClose instead"))- Closed ->- return status- _ -> closeFdWith (closeFd . fromIntegral) (fromIntegral s) >> return Closed+ ConvertedToHandle -> return ConvertedToHandle+ Closed -> return Closed+ _ -> do+ -- closeFdWith avoids the deadlock of IO manager.+ closeFdWith (void . c_close . fromIntegral) (fromIntegral s)+ return Closed++-- | Close the socket. This function throws exceptions if+-- the underlying system call returns errors.+--+-- Sending data to or receiving data from closed socket+-- may lead to undefined behaviour.+close' :: Socket -> IO ()+close' (MkSocket s _ _ _ socketStatus) = modifyMVar_ socketStatus $ \ status ->+ case status of+ ConvertedToHandle -> ioError (userError ("close: converted to a Handle, use hClose instead"))+ Closed -> return Closed+ _ -> do+ -- closeFdWith avoids the deadlock of IO manager.+ -- closeFd throws exceptions.+ closeFdWith (closeFd . fromIntegral) (fromIntegral s)+ return Closed -- -----------------------------------------------------------------------------
Network/Socket/ByteString/Lazy/Posix.hs view
@@ -1,5 +1,7 @@ {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+ module Network.Socket.ByteString.Lazy.Posix ( -- * Send data to a socket@@ -50,6 +52,7 @@ sendAll :: Socket -- ^ Connected socket -> ByteString -- ^ Data to send -> IO ()+sendAll _ "" = return () sendAll sock bs = do sent <- send sock bs waitWhen0 (fromIntegral sent) sock
Network/Socket/ByteString/Lazy/Windows.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+ module Network.Socket.ByteString.Lazy.Windows ( -- * Send data to a socket@@ -31,6 +33,7 @@ sendAll :: Socket -- ^ Connected socket -> L.ByteString -- ^ Data to send -> IO ()+sendAll _ "" = return () sendAll sock bs = do sent <- send sock bs waitWhen0 (fromIntegral sent) sock
Network/Socket/Types.hsc view
@@ -87,6 +87,21 @@ {-# DEPRECATED MkSocket "'MkSocket' will not be available in version 3.0.0.0 or later. Use fdSocket instead" #-} -- | Obtaining the file descriptor from a socket.+--+-- If a 'Socket' is shared with multiple threads and+-- one uses 'fdSocket', unexpected issues may happen.+-- Consider the following scenario:+--+-- 1) Thread A acquires a 'Fd' from 'Socket' by 'fdSocket'.+--+-- 2) Thread B close the 'Socket'.+--+-- 3) Thread C opens a new 'Socket'. Unfortunately it gets the same 'Fd'+-- number which thread A is holding.+--+-- In this case, it is safer for Thread A to clone 'Fd' by+-- 'System.Posix.IO.dup'. But this would still suffer from+-- a rase condition between 'fdSocket' and 'close'. fdSocket :: Socket -> CInt fdSocket (MkSocket fd _ _ _ _) = fd
configure.ac view
@@ -1,4 +1,4 @@-AC_INIT([Haskell network package], [2.7.0.1], [libraries@haskell.org], [network])+AC_INIT([Haskell network package], [2.7.0.2], [libraries@haskell.org], [network]) ac_includes_default="$ac_includes_default #ifdef HAVE_SYS_SOCKET_H
network.cabal view
@@ -1,5 +1,5 @@ name: network-version: 2.7.0.1+version: 2.7.0.2 license: BSD3 license-file: LICENSE maintainer: Kazu Yamamoto, Evan Borden@@ -69,8 +69,8 @@ extensions: CPP, DeriveDataTypeable, ForeignFunctionInterface, TypeSynonymInstances include-dirs: include- includes: HsNet.h- install-includes: HsNet.h+ includes: HsNet.h HsNetDef.h+ install-includes: HsNet.h HsNetDef.h c-sources: cbits/HsNet.c ghc-options: -Wall -fwarn-tabs
tests/SimpleSpec.hs view
@@ -11,8 +11,10 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as S import qualified Data.ByteString.Char8 as C+import qualified Data.ByteString.Lazy as L import Network.Socket hiding (send, sendTo, recv, recvFrom) import Network.Socket.ByteString+import qualified Network.Socket.ByteString.Lazy as Lazy import System.Directory import System.Timeout (timeout) @@ -33,6 +35,12 @@ it "works well" $ do let server sock = recv sock 1024 `shouldReturn` testMsg client sock = sendAll sock testMsg+ tcpTest client server++ describe "Lazy.sendAll" $ do+ it "works well" $ do+ let server sock = recv sock 1024 `shouldReturn` testMsg+ client sock = Lazy.sendAll sock $ L.fromChunks [testMsg] tcpTest client server describe "sendTo" $ do