@@ -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,35 @@ 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 -> if isAlreadyInUseError e then pure () else ioError e
81+
82+ close sock0
83+
84+ -- Unix systems tend to leave the file existing, which is
85+ -- why our `bind` does its workaround. however if any
86+ -- system in the future does fix this issue, we don't want
87+ -- this test to fail, since that would defeat the purpose
88+ -- of our workaround. but you can uncomment the below lines
89+ -- if you want to play with this on your own system.
90+ -- import System.Directory (doesPathExist)
91+ -- ex <- doesPathExist sfile
92+ -- unless ex $ error "socket file was deleted unexpectedly"
93+
94+ sock2 <- socket AF_UNIX Stream defaultProtocol
95+ bind sock2 addr
96+
6697 describe " UserTimeout" $ do
6798 it " can be set" $ do
6899 when (isSupportedSocketOption UserTimeout ) $ do
0 commit comments