-
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
Fix memory leak in getaddrinfo and make it async exception safe #591
base: master
Are you sure you want to change the base?
Conversation
haskell#587 removed the call to `c_freeaddrinfo` in `getaddrinfo`. This restores it and in addition makes the function async exception safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for bringing this issue.
This is a nice catch.
This is a common pattern.
So, I would like you to check if bracketOnError
can be used instead of mask
.
|
I meant |
See the following definition. It uses the same pattern as you wrote. bracketOnError
:: IO a -- ^ computation to run first (\"acquire resource\")
-> (a -> IO b) -- ^ computation to run last (\"release resource\")
-> (a -> IO c) -- ^ computation to run in-between
-> IO c -- returns the value from the in-between computation
bracketOnError before after thing =
mask $ \restore -> do
a <- before
restore (thing a) `onException` after a |
@kazu-yamamoto seems to me that the result of |
Not really, because I used In any case, I tried to use bracket
(do ret <- c_getaddrinfo c_node c_service c_hints ptr_ptr_addrs
ptr_addrs <- if ret == 0
then peek ptr_ptr_addrs
else return nullPtr
return (ret, ptr_addrs)
)
(\(ret, ptr_addrs) -> do
-- Don't call freeaddrinfo with NULL, it segfaults on some
-- platforms.
when (ret == 0) $ c_freeaddrinfo ptr_addrs
)
(\(ret, ptr_addrs) ->
if ret == 0
then followAddrInfo ptr_addrs
else do
err <- gai_strerror ret
ioError $ ioeSetErrorString
(mkIOError NoSuchThing message Nothing Nothing)
err
) that's why I unrolled it in the first place and I don't think trying to force it is worth it. If you disagree, please fix it the way you like. Also, please make a new release with this fix asap and deprecate 3.2.3.0, 3.2.4.0, 3.2.5.0 and 3.2.6.0 on Hackage because this is a very serious bug. |
How about something like this? getAddrs = do
ret <- c_getaddrinfo c_node c_service c_hints
if ret == 0
then Right <$> peek ptr_ptr_addrs
else pure $ Left ret
addrErr ret = do
err <- gai_strerror ret
ioError $ ioeSetErrorString
(mkIOError NoSuchThing message Nothing Nothing)
err
bracket
getAddrs
(mapM_ c_freeaddrinfo)
(either addrErr followAddrInfo) |
You are right. After this discussion, the original PR code is simplest, I think. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now LGTM.
v3.2.7.0 has been released. |
@kazu-yamamoto |
My bad. X-( |
#587 removed the call to
c_freeaddrinfo
ingetaddrinfo
.This restores it and in addition makes the function async exception safe.