@@ -11,6 +11,8 @@ import Network.Socket
1111import Network.Socket.ByteString
1212import Network.Test.Common
1313import System.Mem (performGC )
14+ import System.IO.Error (tryIOError , isAlreadyInUseError )
15+ import System.IO.Temp (withSystemTempDirectory )
1416
1517import Test.Hspec
1618
@@ -63,6 +65,36 @@ spec = do
6365 sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
6466 bind sock (addrAddress addr) `shouldThrow` anyIOException
6567
68+ it " successfully binds to a unix socket, twice" $ do
69+ withSystemTempDirectory " haskell-network" $ \ path -> do
70+ let sfile = path ++ " /socket-file"
71+ let addr = SockAddrUnix sfile
72+ when (isSupportedSockAddr addr) $ do
73+ sock0 <- socket AF_UNIX Stream defaultProtocol
74+ bind sock0 addr
75+ listen sock0 1
76+
77+ sock1 <- socket AF_UNIX Stream defaultProtocol
78+ tryIOError (bind sock1 addr) >>= \ o -> case o of
79+ Right () -> error " bind should have failed but succeeded"
80+ Left e | not (isAlreadyInUseError e) -> ioError e
81+ _ -> return ()
82+
83+ close sock0
84+
85+ -- Unix systems tend to leave the file existing, which is
86+ -- why our `bind` does its workaround. however if any
87+ -- system in the future does fix this issue, we don't want
88+ -- this test to fail, since that would defeat the purpose
89+ -- of our workaround. but you can uncomment the below lines
90+ -- if you want to play with this on your own system.
91+ -- import System.Directory (doesPathExist)
92+ -- ex <- doesPathExist sfile
93+ -- unless ex $ error "socket file was deleted unexpectedly"
94+
95+ sock2 <- socket AF_UNIX Stream defaultProtocol
96+ bind sock2 addr
97+
6698 describe " UserTimeout" $ do
6799 it " can be set" $ do
68100 when (isSupportedSocketOption UserTimeout ) $ do
0 commit comments