From b5c54282dc54cc861277ae532224775076a4818e Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Fri, 2 Jul 2010 13:02:10 +0000 Subject: [PATCH] Fix a few places where we forgot to close the text codecs (#4029) Each time you invoke :load in GHCi it resets the CAFs, including stdin/stdout/stderr, and each of these was allocating a new iconv_t. --- GHC/IO/Handle.hs | 2 ++ GHC/IO/Handle/FD.hs | 3 +++ GHC/IO/Handle/Internals.hs | 14 +++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/GHC/IO/Handle.hs b/GHC/IO/Handle.hs index bf706e0..0330cb3 100644 --- a/GHC/IO/Handle.hs +++ b/GHC/IO/Handle.hs @@ -270,6 +270,7 @@ hSetEncoding :: Handle -> TextEncoding -> IO () hSetEncoding hdl encoding = do withAllHandles__ "hSetEncoding" hdl $ \h_@Handle__{..} -> do flushCharBuffer h_ + closeTextCodecs h_ openTextEncoding (Just encoding) haType $ \ mb_encoder mb_decoder -> do bbuf <- readIORef haByteBuffer ref <- newIORef (error "last_decode") @@ -572,6 +573,7 @@ hSetBinaryMode handle bin = withAllHandles__ "hSetBinaryMode" handle $ \ h_@Handle__{..} -> do flushCharBuffer h_ + closeTextCodecs h_ let mb_te | bin = Nothing | otherwise = Just localeEncoding diff --git a/GHC/IO/Handle/FD.hs b/GHC/IO/Handle/FD.hs index 227816b..98b7472 100644 --- a/GHC/IO/Handle/FD.hs +++ b/GHC/IO/Handle/FD.hs @@ -84,6 +84,9 @@ stdHandleFinalizer :: FilePath -> MVar Handle__ -> IO () stdHandleFinalizer fp m = do h_ <- takeMVar m flushWriteBuffer h_ + case haType h_ of + ClosedHandle -> return () + _other -> closeTextCodecs h_ putMVar m (ioe_finalizedHandle fp) -- We have to put the FDs into binary mode on Windows to avoid the newline diff --git a/GHC/IO/Handle/Internals.hs b/GHC/IO/Handle/Internals.hs index 3c6497c..2c0523f 100644 --- a/GHC/IO/Handle/Internals.hs +++ b/GHC/IO/Handle/Internals.hs @@ -28,7 +28,7 @@ module GHC.IO.Handle.Internals ( wantSeekableHandle, mkHandle, mkFileHandle, mkDuplexHandle, - openTextEncoding, initBufferState, + openTextEncoding, closeTextCodecs, initBufferState, dEFAULT_CHAR_BUFFER_SIZE, flushBuffer, flushWriteBuffer, flushWriteBuffer_, flushCharReadBuffer, @@ -50,7 +50,7 @@ module GHC.IO.Handle.Internals ( import GHC.IO import GHC.IO.IOMode -import GHC.IO.Encoding +import GHC.IO.Encoding as Encoding import GHC.IO.Handle.Types import GHC.IO.Buffer import GHC.IO.BufferedIO (BufferedIO) @@ -632,6 +632,11 @@ openTextEncoding (Just TextEncoding{..}) ha_type cont = do return Nothing cont mb_encoder mb_decoder +closeTextCodecs :: Handle__ -> IO () +closeTextCodecs Handle__{..} = do + case haDecoder of Nothing -> return (); Just d -> Encoding.close d + case haEncoder of Nothing -> return (); Just d -> Encoding.close d + -- --------------------------------------------------------------------------- -- closing Handles @@ -657,7 +662,7 @@ trymaybe :: IO () -> IO (Maybe SomeException) trymaybe io = (do io; return Nothing) `catchException` \e -> return (Just e) hClose_handle_ :: Handle__ -> IO (Handle__, Maybe SomeException) -hClose_handle_ Handle__{..} = do +hClose_handle_ h_@Handle__{..} = do -- close the file descriptor, but not when this is the read -- side of a duplex handle. @@ -676,8 +681,7 @@ hClose_handle_ Handle__{..} = do writeIORef haByteBuffer noByteBuffer -- release our encoder/decoder - case haDecoder of Nothing -> return (); Just d -> close d - case haEncoder of Nothing -> return (); Just d -> close d + closeTextCodecs h_ -- we must set the fd to -1, because the finalizer is going -- to run eventually and try to close/unlock it. -- 1.7.10.4