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.
hSetEncoding hdl encoding = do
withAllHandles__ "hSetEncoding" hdl $ \h_@Handle__{..} -> do
flushCharBuffer h_
hSetEncoding hdl encoding = do
withAllHandles__ "hSetEncoding" hdl $ \h_@Handle__{..} -> do
flushCharBuffer h_
openTextEncoding (Just encoding) haType $ \ mb_encoder mb_decoder -> do
bbuf <- readIORef haByteBuffer
ref <- newIORef (error "last_decode")
openTextEncoding (Just encoding) haType $ \ mb_encoder mb_decoder -> do
bbuf <- readIORef haByteBuffer
ref <- newIORef (error "last_decode")
withAllHandles__ "hSetBinaryMode" handle $ \ h_@Handle__{..} ->
do
flushCharBuffer h_
withAllHandles__ "hSetBinaryMode" handle $ \ h_@Handle__{..} ->
do
flushCharBuffer h_
let mb_te | bin = Nothing
| otherwise = Just localeEncoding
let mb_te | bin = Nothing
| otherwise = Just localeEncoding
stdHandleFinalizer fp m = do
h_ <- takeMVar m
flushWriteBuffer h_
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
putMVar m (ioe_finalizedHandle fp)
-- We have to put the FDs into binary mode on Windows to avoid the newline
wantSeekableHandle,
mkHandle, mkFileHandle, mkDuplexHandle,
wantSeekableHandle,
mkHandle, mkFileHandle, mkDuplexHandle,
- openTextEncoding, initBufferState,
+ openTextEncoding, closeTextCodecs, initBufferState,
dEFAULT_CHAR_BUFFER_SIZE,
flushBuffer, flushWriteBuffer, flushWriteBuffer_, flushCharReadBuffer,
dEFAULT_CHAR_BUFFER_SIZE,
flushBuffer, flushWriteBuffer, flushWriteBuffer_, flushCharReadBuffer,
import GHC.IO
import GHC.IO.IOMode
import GHC.IO
import GHC.IO.IOMode
+import GHC.IO.Encoding as Encoding
import GHC.IO.Handle.Types
import GHC.IO.Buffer
import GHC.IO.BufferedIO (BufferedIO)
import GHC.IO.Handle.Types
import GHC.IO.Buffer
import GHC.IO.BufferedIO (BufferedIO)
return Nothing
cont mb_encoder mb_decoder
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
-- ---------------------------------------------------------------------------
-- closing Handles
trymaybe io = (do io; return Nothing) `catchException` \e -> return (Just e)
hClose_handle_ :: Handle__ -> IO (Handle__, 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.
-- close the file descriptor, but not when this is the read
-- side of a duplex handle.
writeIORef haByteBuffer noByteBuffer
-- release our encoder/decoder
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
-- we must set the fd to -1, because the finalizer is going
-- to run eventually and try to close/unlock it.
-- we must set the fd to -1, because the finalizer is going
-- to run eventually and try to close/unlock it.