Skip to content

Commit 9da532e

Browse files
complyuekazu-yamamoto
authored andcommitted
fix socket leakage on setup errors, e.g. binding for a server socket, connecting for a client socket
1 parent 7cbbdb5 commit 9da532e

File tree

3 files changed

+32
-28
lines changed

3 files changed

+32
-28
lines changed

Network/Socket.hs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,17 @@
5252
-- > , addrSocketType = Stream
5353
-- > }
5454
-- > head <$> getAddrInfo (Just hints) mhost (Just port)
55-
-- > open addr = do
56-
-- > sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
57-
-- > setSocketOption sock ReuseAddr 1
58-
-- > withFdSocket sock setCloseOnExecIfNeeded
59-
-- > bind sock $ addrAddress addr
60-
-- > listen sock 1024
61-
-- > return sock
62-
-- > loop sock = forever $ do
63-
-- > (conn, _peer) <- accept sock
64-
-- > void $ forkFinally (server conn) (const $ gracefulClose conn 5000)
55+
-- > open addr = E.bracketOnError
56+
-- > (socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
57+
-- > close $ \sock -> do
58+
-- > setSocketOption sock ReuseAddr 1
59+
-- > withFdSocket sock setCloseOnExecIfNeeded
60+
-- > bind sock $ addrAddress addr
61+
-- > listen sock 1024
62+
-- > return sock
63+
-- > loop sock = forever $ E.bracketOnError (accept sock) (close . fst)
64+
-- > $ \(conn, _peer) -> void $
65+
-- > forkFinally (server conn) (const $ gracefulClose conn 5000)
6566
--
6667
-- > {-# LANGUAGE OverloadedStrings #-}
6768
-- > -- Echo client program
@@ -88,10 +89,11 @@
8889
-- > resolve = do
8990
-- > let hints = defaultHints { addrSocketType = Stream }
9091
-- > head <$> getAddrInfo (Just hints) (Just host) (Just port)
91-
-- > open addr = do
92-
-- > sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
93-
-- > connect sock $ addrAddress addr
94-
-- > return sock
92+
-- > open addr = E.bracketOnError
93+
-- > (socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
94+
-- > close $ \sock -> do
95+
-- > connect sock $ addrAddress addr
96+
-- > return sock
9597
--
9698
-- The proper programming model is that one 'Socket' is handled by
9799
-- a single thread. If multiple threads use one 'Socket' concurrently,

examples/EchoClient.hs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ runTCPClient host port client = withSocketsDo $ do
2323
resolve = do
2424
let hints = defaultHints { addrSocketType = Stream }
2525
head <$> getAddrInfo (Just hints) (Just host) (Just port)
26-
open addr = do
27-
sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
28-
connect sock $ addrAddress addr
29-
return sock
26+
open addr = E.bracketOnError
27+
(socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
28+
close $ \sock -> do
29+
connect sock $ addrAddress addr
30+
return sock

examples/EchoServer.hs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ runTCPServer mhost port server = withSocketsDo $ do
2929
, addrSocketType = Stream
3030
}
3131
head <$> getAddrInfo (Just hints) mhost (Just port)
32-
open addr = do
33-
sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
34-
setSocketOption sock ReuseAddr 1
35-
withFdSocket sock setCloseOnExecIfNeeded
36-
bind sock $ addrAddress addr
37-
listen sock 1024
38-
return sock
39-
loop sock = forever $ do
40-
(conn, _peer) <- accept sock
41-
void $ forkFinally (server conn) (const $ gracefulClose conn 5000)
32+
open addr = E.bracketOnError
33+
(socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
34+
close $ \sock -> do
35+
setSocketOption sock ReuseAddr 1
36+
withFdSocket sock setCloseOnExecIfNeeded
37+
bind sock $ addrAddress addr
38+
listen sock 1024
39+
return sock
40+
loop sock = forever $ E.bracketOnError (accept sock) (close . fst)
41+
$ \(conn, _peer) -> void $
42+
forkFinally (server conn) (const $ gracefulClose conn 5000)

0 commit comments

Comments
 (0)