Skip to content

Commit c8a0843

Browse files
infinity0kazu-yamamoto
authored andcommitted
bind: gracefully handle the fact that UNIX systems don't clean up closed UNIX domain sockets
inspired by https://stackoverflow.com/a/13719866
1 parent 37e43d2 commit c8a0843

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

Network/Socket/SockAddr.hs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ module Network.Socket.SockAddr (
1111
, recvBufMsg
1212
) where
1313

14+
import Control.Exception (try, throwIO, IOException)
15+
import System.Directory (removeFile)
16+
import System.IO.Error (isAlreadyInUseError, isDoesNotExistError)
17+
1418
import qualified Network.Socket.Buffer as G
1519
import qualified Network.Socket.Name as G
1620
import qualified Network.Socket.Syscall as G
@@ -41,7 +45,27 @@ connect = G.connect
4145
-- 'defaultPort' is passed then the system assigns the next available
4246
-- use port.
4347
bind :: Socket -> SockAddr -> IO ()
44-
bind = G.bind
48+
bind s a = case a of
49+
SockAddrUnix p -> do
50+
-- gracefully handle the fact that UNIX systems don't clean up closed UNIX
51+
-- domain sockets, inspired by https://stackoverflow.com/a/13719866
52+
res <- try (G.bind s a)
53+
case res of
54+
Right () -> pure ()
55+
Left e -> if not (isAlreadyInUseError (e :: IOException))
56+
then throwIO e
57+
else do
58+
-- socket might be in use, try to connect
59+
res2 <- try (G.connect s a)
60+
case res2 of
61+
Right () -> close s >> throwIO e
62+
Left e2 -> if not (isDoesNotExistError (e2 :: IOException))
63+
then throwIO e
64+
else do
65+
-- socket not actually in use, remove it and retry bind
66+
removeFile p
67+
G.bind s a
68+
_ -> G.bind s a
4569

4670
-- | Accept a connection. The socket must be bound to an address and
4771
-- listening for connections. The return value is a pair @(conn,

network.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ library
8383
build-depends:
8484
base >= 4.7 && < 5,
8585
bytestring == 0.10.*,
86-
deepseq
86+
deepseq,
87+
directory
8788

8889
include-dirs: include
8990
includes: HsNet.h HsNetDef.h alignment.h win32defs.h

0 commit comments

Comments
 (0)