|
1 | 1 | {-# LANGUAGE CPP #-} |
| 2 | +{-# LANGUAGE ScopedTypeVariables #-} |
2 | 3 |
|
3 | 4 | #include "HsNetDef.h" |
4 | 5 |
|
@@ -59,7 +60,8 @@ gracefulClose s tmout0 = sendRecvFIN `E.finally` close s |
59 | 60 | -- Sending TCP FIN. |
60 | 61 | ex <- E.try $ shutdown s ShutdownSend |
61 | 62 | case ex of |
62 | | - Left (E.SomeException _) -> return () |
| 63 | + -- Don't catch asynchronous exceptions |
| 64 | + Left (_ :: E.IOException) -> return () |
63 | 65 | Right () -> do |
64 | 66 | -- Giving CPU time to other threads hoping that |
65 | 67 | -- FIN arrives meanwhile. |
@@ -93,29 +95,26 @@ recvEOFevent :: Socket -> Int -> Ptr Word8 -> IO () |
93 | 95 | recvEOFevent s tmout0 buf = do |
94 | 96 | tmmgr <- Ev.getSystemTimerManager |
95 | 97 | tvar <- newTVarIO False |
96 | | - E.bracket (setup tmmgr tvar) teardown $ \(wait, _) -> do |
97 | | - waitRes <- wait |
98 | | - case waitRes of |
99 | | - TimeoutTripped -> return () |
100 | | - -- We don't check the (positive) length. |
101 | | - -- In normal case, it's 0. That is, only FIN is received. |
102 | | - -- In error cases, data is available. But there is no |
103 | | - -- application which can read it. So, let's stop receiving |
104 | | - -- to prevent attacks. |
105 | | - MoreData -> void $ recvBufNoWait s buf bufSize |
| 98 | + E.bracket (setupTimeout tmmgr tvar) (cancelTimeout tmmgr) $ \_ -> do |
| 99 | + E.bracket (setupRead s) cancelRead $ \(rxWait,_) -> do |
| 100 | + let toWait = readTVar tvar >>= check |
| 101 | + wait = atomically ((toWait >> return TimeoutTripped) |
| 102 | + <|> (rxWait >> return MoreData)) |
| 103 | + waitRes <- wait |
| 104 | + case waitRes of |
| 105 | + TimeoutTripped -> return () |
| 106 | + -- We don't check the (positive) length. |
| 107 | + -- In normal case, it's 0. That is, only FIN is received. |
| 108 | + -- In error cases, data is available. But there is no |
| 109 | + -- application which can read it. So, let's stop receiving |
| 110 | + -- to prevent attacks. |
| 111 | + MoreData -> void $ recvBufNoWait s buf bufSize |
106 | 112 | where |
107 | | - setup tmmgr tvar = do |
108 | | - -- millisecond to microsecond |
109 | | - key <- Ev.registerTimeout tmmgr (tmout0 * 1000) $ |
110 | | - atomically $ writeTVar tvar True |
111 | | - (evWait, evCancel) <- waitAndCancelReadSocketSTM s |
112 | | - let toWait = do |
113 | | - tmout <- readTVar tvar |
114 | | - check tmout |
115 | | - toCancel = Ev.unregisterTimeout tmmgr key |
116 | | - wait = atomically ((toWait >> return TimeoutTripped) |
117 | | - <|> (evWait >> return MoreData)) |
118 | | - cancel = evCancel >> toCancel |
119 | | - return (wait, cancel) |
120 | | - teardown (_, cancel) = cancel |
| 113 | + -- millisecond to microsecond |
| 114 | + tmout = tmout0 * 1000 |
| 115 | + setupTimeout tmmgr tvar = |
| 116 | + Ev.registerTimeout tmmgr tmout $ atomically $ writeTVar tvar True |
| 117 | + cancelTimeout = Ev.unregisterTimeout |
| 118 | + setupRead = waitAndCancelReadSocketSTM |
| 119 | + cancelRead (_,cancel) = cancel |
121 | 120 | #endif |
0 commit comments