@@ -11,6 +11,8 @@ import Network.Socket
11
11
import Network.Socket.ByteString
12
12
import Network.Test.Common
13
13
import System.Mem (performGC )
14
+ import System.IO.Error (tryIOError , isAlreadyInUseError )
15
+ import System.IO.Temp (withSystemTempDirectory )
14
16
15
17
import Test.Hspec
16
18
@@ -63,6 +65,35 @@ spec = do
63
65
sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
64
66
bind sock (addrAddress addr) `shouldThrow` anyIOException
65
67
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
+
66
97
describe " UserTimeout" $ do
67
98
it " can be set" $ do
68
99
when (isSupportedSocketOption UserTimeout ) $ do
0 commit comments