diff options
author | Tamar Christina <tamar@zhox.com> | 2021-12-28 15:06:16 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-01-15 03:41:55 -0500 |
commit | 0dc723957d0fdb5909f145405b775efea0fe2f6e (patch) | |
tree | f6ee9f0a8ec293c4d6b60e6d6cb8cdb7b67ec082 | |
parent | e2b60be8472ad5b7b6ef2b265b4a06d1b2b67c7d (diff) | |
download | haskell-0dc723957d0fdb5909f145405b775efea0fe2f6e.tar.gz |
winio: fix heap corruption and various leaks.
-rw-r--r-- | libraries/base/GHC/Event/Windows.hsc | 5 | ||||
-rw-r--r-- | libraries/base/GHC/IO/Windows/Paths.hs | 2 | ||||
-rw-r--r-- | libraries/base/System/IO.hs | 24 | ||||
-rw-r--r-- | libraries/base/cbits/Win32Utils.c | 4 | ||||
-rw-r--r-- | rts/RtsStartup.c | 3 | ||||
-rw-r--r-- | rts/RtsSymbols.c | 3 | ||||
-rw-r--r-- | rts/include/rts/IOInterface.h | 1 | ||||
-rw-r--r-- | rts/win32/AsyncWinIO.c | 3 | ||||
-rw-r--r-- | rts/win32/ConsoleHandler.c | 2 | ||||
-rw-r--r-- | rts/win32/ConsoleHandler.h | 7 | ||||
-rw-r--r-- | rts/win32/ThrIOManager.c | 10 | ||||
-rw-r--r-- | rts/win32/ThrIOManager.h | 2 |
12 files changed, 46 insertions, 20 deletions
diff --git a/libraries/base/GHC/Event/Windows.hsc b/libraries/base/GHC/Event/Windows.hsc index b97250e897..cc6bbaa927 100644 --- a/libraries/base/GHC/Event/Windows.hsc +++ b/libraries/base/GHC/Event/Windows.hsc @@ -1162,7 +1162,7 @@ io_mngr_loop _event mgr = go False exit <- case event_id of _ | event_id == io_MANAGER_WAKEUP -> return False - _ | event_id == io_MANAGER_DIE -> return True + _ | event_id == io_MANAGER_DIE -> c_ioManagerFinished >> return True 0 -> return False -- spurious wakeup _ -> do debugIO $ "handling console event: " ++ show (event_id `shiftR` 1) start_console_handler (event_id `shiftR` 1) @@ -1203,6 +1203,9 @@ foreign import ccall unsafe "getIOManagerEvent" -- in the RTS (ThrIOManager.c) foreign import ccall unsafe "readIOManagerEvent" -- in the RTS (ThrIOManager.c) c_readIOManagerEvent :: IO Word32 +foreign import ccall unsafe "ioManagerFinished" -- in the RTS (ThrIOManager.c) + c_ioManagerFinished :: IO () + foreign import ccall unsafe "rtsSupportsBoundThreads" threadedIOMgr :: Bool -- | Sleep for n ms diff --git a/libraries/base/GHC/IO/Windows/Paths.hs b/libraries/base/GHC/IO/Windows/Paths.hs index 851dc37508..c755996f22 100644 --- a/libraries/base/GHC/IO/Windows/Paths.hs +++ b/libraries/base/GHC/IO/Windows/Paths.hs @@ -30,7 +30,7 @@ import GHC.IO import Foreign.C.String import Foreign.Marshal.Alloc (free) -foreign import WINDOWS_CCONV safe "__hs_create_device_name" +foreign import ccall safe "__hs_create_device_name" c_GetDevicePath :: CWString -> IO CWString -- | This function converts Windows paths between namespaces. More specifically diff --git a/libraries/base/System/IO.hs b/libraries/base/System/IO.hs index 265507d970..f831df6cb4 100644 --- a/libraries/base/System/IO.hs +++ b/libraries/base/System/IO.hs @@ -231,13 +231,13 @@ import Foreign.C.Error import Foreign.C.String import Foreign.Ptr import Foreign.Marshal.Alloc +import Foreign.Marshal.Utils (with) import Foreign.Storable import GHC.IO.SubSystem import GHC.IO.Windows.Handle (openFileAsTemp) import GHC.IO.Handle.Windows (mkHandleFromHANDLE) import GHC.IO.Device as IODevice import GHC.Real (fromIntegral) -import Foreign.Marshal.Utils (new) #endif import Foreign.C.Types import System.Posix.Internals @@ -529,17 +529,17 @@ openTempFile' loc tmp_dir template binary mode let label = if null prefix then "ghc" else prefix withCWString tmp_dir $ \c_tmp_dir -> withCWString label $ \c_template -> - withCWString suffix $ \c_suffix -> do - c_ptr <- new nullPtr - res <- c_createUUIDTempFileErrNo c_tmp_dir c_template c_suffix - c_ptr - if not res - then do errno <- getErrno - ioError (errnoToIOError loc errno Nothing (Just tmp_dir)) - else do c_p <- peek c_ptr - filename <- peekCWString c_p - free c_p - handleResultsWinIO filename ((fromIntegral mode .&. o_EXCL) == o_EXCL) + withCWString suffix $ \c_suffix -> + with nullPtr $ \c_ptr -> do + res <- c_createUUIDTempFileErrNo c_tmp_dir c_template c_suffix c_ptr + if not res + then do errno <- getErrno + ioError (errnoToIOError loc errno Nothing (Just tmp_dir)) + else do c_p <- peek c_ptr + filename <- peekCWString c_p + free c_p + let flags = fromIntegral mode .&. o_EXCL + handleResultsWinIO filename (flags == o_EXCL) findTempNamePosix = do let label = if null prefix then "ghc" else prefix diff --git a/libraries/base/cbits/Win32Utils.c b/libraries/base/cbits/Win32Utils.c index f3dec0d98d..69d30339ba 100644 --- a/libraries/base/cbits/Win32Utils.c +++ b/libraries/base/cbits/Win32Utils.c @@ -183,10 +183,9 @@ bool __createUUIDTempFileErrNo (wchar_t* pathName, wchar_t* prefix, RPC_WSTR guidStr; if (UuidToStringW ((UUID*)&guid, &guidStr) != S_OK) goto fail; - /* We can't create a device path here since this path escapes the compiler so instead return a normal path and have openFile deal with it. */ - wchar_t* devName = malloc (sizeof (wchar_t) * wcslen (pathName)); + wchar_t* devName = malloc (sizeof (wchar_t) * (wcslen (pathName) + 1)); wcscpy (devName, pathName); int len = wcslen (devName) + wcslen (suffix) + wcslen (prefix) + wcslen (guidStr) + 3; @@ -204,6 +203,7 @@ bool __createUUIDTempFileErrNo (wchar_t* pathName, wchar_t* prefix, free (devName); RpcStringFreeW (&guidStr); + /* This should never happen because GUIDs are unique. But in case hell froze over let's check anyway. */ DWORD dwAttrib = GetFileAttributesW (*tempFileName); diff --git a/rts/RtsStartup.c b/rts/RtsStartup.c index 86d5b2f2d9..07db7b7998 100644 --- a/rts/RtsStartup.c +++ b/rts/RtsStartup.c @@ -578,6 +578,9 @@ hs_exit_(bool wait_foreign) #if defined(mingw32_HOST_OS) if (is_io_mng_native_p()) hs_restoreConsoleCP(); + + /* Disable console signal handlers, we're going down!. */ + finiUserSignals (); #endif /* tear down statistics subsystem */ diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c index 894e9ff305..b6440049c0 100644 --- a/rts/RtsSymbols.c +++ b/rts/RtsSymbols.c @@ -375,13 +375,14 @@ extern char **environ; SymI_HasProto(unblockUserSignals) #else #define RTS_USER_SIGNALS_SYMBOLS \ - SymI_HasProto(registerIOCPHandle) \ + SymI_HasProto(registerIOCPHandle) \ SymI_HasProto(getOverlappedEntries) \ SymI_HasProto(completeSynchronousRequest) \ SymI_HasProto(registerAlertableWait) \ SymI_HasProto(sendIOManagerEvent) \ SymI_HasProto(readIOManagerEvent) \ SymI_HasProto(getIOManagerEvent) \ + SymI_HasProto(ioManagerFinished) \ SymI_HasProto(console_handler) #endif diff --git a/rts/include/rts/IOInterface.h b/rts/include/rts/IOInterface.h index 9a646cc5cf..fd625eda70 100644 --- a/rts/include/rts/IOInterface.h +++ b/rts/include/rts/IOInterface.h @@ -27,6 +27,7 @@ extern StgInt console_handler; void * getIOManagerEvent (void); HsWord32 readIOManagerEvent (void); void sendIOManagerEvent (HsWord32 event); +void ioManagerFinished (void); #else diff --git a/rts/win32/AsyncWinIO.c b/rts/win32/AsyncWinIO.c index 7fb71e92e7..5f61f815f3 100644 --- a/rts/win32/AsyncWinIO.c +++ b/rts/win32/AsyncWinIO.c @@ -147,7 +147,7 @@ There we initialize IO manager locale variables and. * call ioManagerStart() - * Creat a thread to execute "runner" + * Create a thread to execute "runner" We never truly shut down the IO Manager. While this means we might block forever on the IOPort if the IO Manager is no longer @@ -274,6 +274,7 @@ void shutdownAsyncWinIO(bool wait_threads) WaitForSingleObject (workerThread, INFINITE); } completionPortHandle = INVALID_HANDLE_VALUE; + CloseHandle (workerThread); workerThread = NULL; workerThreadId = 0; free (entries); diff --git a/rts/win32/ConsoleHandler.c b/rts/win32/ConsoleHandler.c index 05d15868eb..4af897bc54 100644 --- a/rts/win32/ConsoleHandler.c +++ b/rts/win32/ConsoleHandler.c @@ -57,7 +57,7 @@ freeSignalHandlers(void) { /* Do nothing */ } -/* Seems to be a bit of an orphan...where used? */ +/* Called in hs_exit to clean up resources. */ void finiUserSignals(void) { diff --git a/rts/win32/ConsoleHandler.h b/rts/win32/ConsoleHandler.h index bb7278abba..d22f10f16a 100644 --- a/rts/win32/ConsoleHandler.h +++ b/rts/win32/ConsoleHandler.h @@ -62,3 +62,10 @@ extern void startSignalHandlers(Capability *cap); extern int rts_waitConsoleHandlerCompletion(void); #endif /* THREADED_RTS */ + +/* + * Function: finiUserSignals() + * + * Tear down and shut down user signal processing. + */ +extern void finiUserSignals(void); diff --git a/rts/win32/ThrIOManager.c b/rts/win32/ThrIOManager.c index d614d49a0c..6bbf65a45f 100644 --- a/rts/win32/ThrIOManager.c +++ b/rts/win32/ThrIOManager.c @@ -161,3 +161,13 @@ ioManagerStart (void) rts_unlock(cap); } } + +/* + * Called to close the io_manager_event handle when the IO manager thread is + * terminating. + */ +void +ioManagerFinished(void) +{ + CloseHandle(io_manager_event); +} diff --git a/rts/win32/ThrIOManager.h b/rts/win32/ThrIOManager.h index a67bdde364..c7ecc76e9f 100644 --- a/rts/win32/ThrIOManager.h +++ b/rts/win32/ThrIOManager.h @@ -15,4 +15,4 @@ void ioManagerWakeup (void); void ioManagerDie (void); void ioManagerStart (void); - +void ioManagerFinished (void); |