-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GCing Sockets is a bad diea #302
Comments
Was there really a version 2.6.3.4? I don't see it anywhere... If it had no finalizers defined, its close API was still OK, and safe for repeated calls. |
See #300. |
But I do see #269, so I guess that was it... |
My proposal is release 2.6.3.4, 2.7.0.0 and 3.0.0.0 in order. If @eborden agree with this, we will carry out this plan.
See also #296. |
@vdukhovni Sorry for your confusion. My plan is to override
|
To be honest I am not sure that removing the If performance is not impacted, I'd even consider storing the file descriptor in an IORef, and replace it with |
For |
After releasing 2.7.0.0, we should wait for a long time so that users of network library stop using deprecated APIs. So, we have enough time. Let's continue discussion. |
For example,
I see just one close:
Likely |
Your requirement is:
Right? |
It's worth confirming that |
No, rather a Socket that is still reachable must remember that it is already closed, so that a second close will not close the
Actually it is OK to throw an error, but perhaps not needed (System.IO handles seem to not bother) just don't do it in a finalizer. If you throw on close, then also provide some sort of
I guess not, but is the above more clear? |
Of course it GC's just fine, there's no |
If we are to utilize an |
@eborden I don't understand why |
Well, actually, if the Socket does contain a mutable IORef with the file-descriptor inside it, then you can ensure that |
Here's a small demo of the possible finalization approach. (Whether finalization is a good idea is still an open question in my mind, perhaps most applications don't need this, and perhaps the cost of adding it is noticeable? But if it is cheap enough, then perhaps worth it, for those applications that neglect to clean up). module Main (main) where
import Data.IORef
import System.Mem
import Control.Monad (void)
myClose :: IORef Int -> IO ()
myClose r = do
old <- atomicModifyIORef' r $ \old -> (-1, old)
case old of
-1 -> return ()
_ -> putStrLn $ "Closing: r" ++ show old
main :: IO ()
main = do
r1 <- newIORef 1
r2 <- newIORef 2
r3 <- newIORef 3
void $ mkWeakIORef r1 $ myClose r1
void $ mkWeakIORef r2 $ myClose r2
void $ mkWeakIORef r3 $ myClose r3
myClose r2
myClose r3
myClose r3
performGC Running it shows exactly one close for each of the three objects, one closed when finalized, other two closed explicitly by the application, one twice, but all three do the (just print a message) close processing just once.
|
@vdukhovni Thanks! I think that I understand now. |
#303 has been merged. Let's close this. |
Cc: @vdukhovni
We are planning to add a finalizer to
Socket
s so that they can be GCed.GHC's bug 1
In network v2.6.3.4, we use:
The definition of
close
is:So, if a
Socket
is converted intoHandle
and theSocket
becomes unreach,close
is called and an error is thrown. We believed that this is just ignored. Unfortunately, this is not the case. GHC has a bug. If a finalizer throws an error, other finalizers are not called:https://ghc.haskell.org/trac/ghc/ticket/13167
GHC's bug 2
For 3.0.0.0, we are trying to use
addFinalizer
: #301As I already reported, GHC 7.10 GCes
Socket
s too early. I also found that GHC 7.8 has the same bug.Bad usage
A user can close the file descriptor of
Socket
by calling theclose
syscall. Then the user opens another file or socket and the number is reused. In this situation, calling finalizer by GC results in unexpected bug.Proposed actions
mkWeakMVar
for v2.6.3.4Sockets
are not GCed and users SHOULD close them by themselves.The text was updated successfully, but these errors were encountered: