summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamar Christina <tamar@zhox.com>2021-12-28 15:06:16 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2022-01-15 03:41:55 -0500
commit0dc723957d0fdb5909f145405b775efea0fe2f6e (patch)
treef6ee9f0a8ec293c4d6b60e6d6cb8cdb7b67ec082
parente2b60be8472ad5b7b6ef2b265b4a06d1b2b67c7d (diff)
downloadhaskell-0dc723957d0fdb5909f145405b775efea0fe2f6e.tar.gz
winio: fix heap corruption and various leaks.
-rw-r--r--libraries/base/GHC/Event/Windows.hsc5
-rw-r--r--libraries/base/GHC/IO/Windows/Paths.hs2
-rw-r--r--libraries/base/System/IO.hs24
-rw-r--r--libraries/base/cbits/Win32Utils.c4
-rw-r--r--rts/RtsStartup.c3
-rw-r--r--rts/RtsSymbols.c3
-rw-r--r--rts/include/rts/IOInterface.h1
-rw-r--r--rts/win32/AsyncWinIO.c3
-rw-r--r--rts/win32/ConsoleHandler.c2
-rw-r--r--rts/win32/ConsoleHandler.h7
-rw-r--r--rts/win32/ThrIOManager.c10
-rw-r--r--rts/win32/ThrIOManager.h2
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);