packages feed

network-run 0.7.0 → 0.7.1

raw patch · 7 files changed

+53/−11 lines, 7 filesdep ~networkPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: network

API changes (from Hackage documentation)

+ Network.Run.TCP: [settingsUnsafeClose] :: ServerSettings -> Bool
+ Network.Run.TCP.Timeout: [settingsUnsafeClose] :: ServerSettings -> Bool
+ Network.Run.UDP: [settingsUnsafeClose] :: ServerSettings -> Bool
- Network.Run.TCP: ServerSettings :: (Maybe SockAddr -> SomeException -> IO ()) -> Int -> Int -> (IO () -> IO ()) -> ServerSettings
+ Network.Run.TCP: ServerSettings :: (Maybe SockAddr -> SomeException -> IO ()) -> Int -> Bool -> Int -> (IO () -> IO ()) -> ServerSettings
- Network.Run.TCP.Timeout: ServerSettings :: (Maybe SockAddr -> SomeException -> IO ()) -> Int -> Int -> (IO () -> IO ()) -> ServerSettings
+ Network.Run.TCP.Timeout: ServerSettings :: (Maybe SockAddr -> SomeException -> IO ()) -> Int -> Bool -> Int -> (IO () -> IO ()) -> ServerSettings
- Network.Run.UDP: ServerSettings :: (Maybe SockAddr -> SomeException -> IO ()) -> Int -> Int -> (IO () -> IO ()) -> ServerSettings
+ Network.Run.UDP: ServerSettings :: (Maybe SockAddr -> SomeException -> IO ()) -> Int -> Bool -> Int -> (IO () -> IO ()) -> ServerSettings

Files

CHANGELOG.md view
@@ -1,5 +1,16 @@ # Revision history for network-run +## 0.7.1++* Sockets this library owns and has not handed to anyone are closed with+  `close(2)` rather than with `close`, which goes through the IO manager+  to tell a waiter that is not there.+* `settingsUnsafeClose` lets a server close its connections with+  `unsafeGracefulClose` or `unsafeClose`.  The default keeps `close`,+  since only the caller knows whether its handler leaves a thread on the+  socket.+* Requires network 3.2.12.+ ## 0.7.0  * The accept loop is stopped by being told, through the new
Network/Run/Core.hs view
@@ -81,7 +81,7 @@ -- The options are set before 'connect'. openClientSocketWithOpts     :: [(SocketOption, SockOptValue)] -> AddrInfo -> IO Socket-openClientSocketWithOpts opts addr = E.bracketOnError (openSocket addr) close $ \sock -> do+openClientSocketWithOpts opts addr = E.bracketOnError (openSocket addr) unsafeClose $ \sock -> do     mapM_ (uncurry $ setSockOptValue sock) opts     connect sock $ addrAddress addr     return sock@@ -127,7 +127,7 @@ -- cannot be cleared. openServerSocketWithOpts     :: [(SocketOption, SockOptValue)] -> AddrInfo -> IO Socket-openServerSocketWithOpts opts addr = E.bracketOnError (openSocket addr) close $ \sock -> do+openServerSocketWithOpts opts addr = E.bracketOnError (openSocket addr) unsafeClose $ \sock -> do     setSocketOption sock ReuseAddr 1 #if !defined(openbsd_HOST_OS)     when (addrFamily addr == AF_INET6) $ setSocketOption sock IPv6Only 1@@ -206,6 +206,12 @@     -- connection handler returns.  Zero or less uses 'close' instead,     -- which releases the file descriptor immediately.  The default is     -- 5000.+    , settingsUnsafeClose :: Bool+    -- ^ Closing a connected socket with 'unsafeGracefulClose' or+    -- 'unsafeClose', which skip the IO manager that 'close' goes through+    -- to tell a thread waiting on the socket.  Set this only when the+    -- connection handler leaves no thread and no registered wait on the+    -- socket by the time it returns.  The default is 'False'.     , settingsAcceptRetryDelay :: Int     -- ^ Microseconds to wait before retrying 'accept' after running     -- out of file descriptors.  The default is 100000.@@ -235,6 +241,7 @@     ServerSettings         { settingsOnException = \_ _ -> return ()         , settingsGracefulCloseTimeout = 5000+        , settingsUnsafeClose = False         , settingsAcceptRetryDelay = 100000         , settingsInstallShutdownHandler = const $ return ()         }@@ -253,8 +260,12 @@ -- | Closing a connected socket according to the settings. gcloseWith :: ServerSettings -> Socket -> IO () gcloseWith ServerSettings{..} sock-    | settingsGracefulCloseTimeout <= 0 = close sock-    | otherwise = gracefulClose sock settingsGracefulCloseTimeout+    | settingsGracefulCloseTimeout <= 0 = closer sock+    | otherwise = gracefulCloser sock settingsGracefulCloseTimeout+  where+    (closer, gracefulCloser)+        | settingsUnsafeClose = (unsafeClose, unsafeGracefulClose)+        | otherwise = (close, gracefulClose)  ---------------------------------------------------------------- 
Network/Run/TCP.hs view
@@ -54,7 +54,7 @@     -> IO () runTCPServerWithSettings set mhost port server = do     addr <- resolve Stream mhost port [AI_PASSIVE] NE.head-    E.bracket (openTCPServerSocket addr) close $ \sock ->+    E.bracket (openTCPServerSocket addr) unsafeClose $ \sock ->         runTCPServerWithSocketAndSettings set sock server  -- | Running a TCP server on a given listen socket.@@ -83,7 +83,7 @@     -- is closed if anything goes wrong before the thread owning it has     -- been forked.     loop listener = do-        more <- E.bracketOnError (acceptOrStop listener) (mapM_ (close . fst)) $ \maccepted ->+        more <- E.bracketOnError (acceptOrStop listener) (mapM_ (unsafeClose . fst)) $ \maccepted ->             case maccepted of                 Nothing -> return False                 Just (conn, peer) -> do
Network/Run/TCP/Timeout.hs view
@@ -59,7 +59,7 @@     -> IO () runTCPServerWithSettings set tm mhost port server = do     addr <- resolve Stream mhost port [AI_PASSIVE] NE.head-    E.bracket (openTCPServerSocket addr) close $ \sock ->+    E.bracket (openTCPServerSocket addr) unsafeClose $ \sock ->         runTCPServerWithSocketAndSettings set tm sock server  -- | Running a TCP server on a given listen socket.@@ -90,7 +90,7 @@     -- is closed if anything goes wrong before the thread owning it has     -- been forked.     loop listener mgr = do-        more <- E.bracketOnError (acceptOrStop listener) (mapM_ (close . fst)) $ \maccepted ->+        more <- E.bracketOnError (acceptOrStop listener) (mapM_ (unsafeClose . fst)) $ \maccepted ->             case maccepted of                 Nothing -> return False                 Just (conn, peer) -> do
Network/Run/UDP.hs view
@@ -101,7 +101,7 @@             -- If 'connect' throws, the socket is closed here.  On             -- success it is owned by the new thread and is closed by             -- its finalizer.-            E.bracketOnError (openServerSocket addr) close $ \s -> do+            E.bracketOnError (openServerSocket addr) unsafeClose $ \s -> do                 connect s peeraddr                 forkDatagram set s peeraddr $                     labelMe "UDP server" >> server s bs0
network-run.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.0 name:               network-run-version:            0.7.0+version:            0.7.1 license:            BSD3 license-file:       LICENSE maintainer:         kazu@iij.ad.jp@@ -31,7 +31,7 @@     build-depends:         base >=4 && <5,         bytestring >=0.10 && <0.13,-        network >=3.2.10 && <3.3,+        network >=3.2.12 && <3.3,         stm >=2.5 && <2.6,         time-manager >=0.2 && <0.6 
test/TCPSpec.hs view
@@ -150,6 +150,26 @@                     putMVar gate ()                     recv sock 1024 `shouldThrow` anyIOException +        it "drains a connection with unsafeGracefulClose when asked to" $ limited $ do+            gate <- newEmptyMVar+            let set = defaultServerSettings{settingsGracefulCloseTimeout = 500, settingsUnsafeClose = True}+            withTCPServer set (\_ -> takeMVar gate) $ \port ->+                client port $ \sock -> do+                    sendAll sock "hello"+                    threadDelay 200000+                    putMVar gate ()+                    recv sock 1024 `shouldReturn` ""++        it "resets a connection with unsafeClose when asked to" $ limited $ do+            gate <- newEmptyMVar+            let set = defaultServerSettings{settingsGracefulCloseTimeout = 0, settingsUnsafeClose = True}+            withTCPServer set (\_ -> takeMVar gate) $ \port ->+                client port $ \sock -> do+                    sendAll sock "hello"+                    threadDelay 200000+                    putMVar gate ()+                    recv sock 1024 `shouldThrow` anyIOException+         it "serves many connections concurrently" $             limited $                 withTCPServer defaultServerSettings echo $ \port -> do