GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:36:57Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/10236DWARF unwind info is broken2019-07-07T18:36:57ZthoughtpoliceDWARF unwind info is brokenAs reported by `bitonic` and `petermw` on `#ghc` (April 2nd):
```
07:02 < bitonic> I'm trying to get a meaningful backtrace with DWARF, using
<https://ghc.haskell.org/trac/ghc/wiki/DWARF> as a guide. however, all I ge...As reported by `bitonic` and `petermw` on `#ghc` (April 2nd):
```
07:02 < bitonic> I'm trying to get a meaningful backtrace with DWARF, using
<https://ghc.haskell.org/trac/ghc/wiki/DWARF> as a guide. however, all I get is
`Backtrace stopped: previous frame identical to this frame (corrupt stack?)`
07:03 < bitonic> I've re-built GHC 7.10.1 using `GhcRtsHcOpts += -g` and `GhcLibHcOpts += -g`, even if
I'm not sure it's even necessary
07:04 < bitonic> are there any additional steps I should take? or any way to make sure that the binary
I'm generating is sane?
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------------- |
| Version | 7.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | Compiler (Debugging) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | scpmw |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"DWARF unwind info is broken","status":"New","operating_system":"","component":"Compiler (Debugging)","related":[],"milestone":"7.10.2","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.1","keywords":["dwarf"],"differentials":[],"test_case":"","architecture":"","cc":["scpmw"],"type":"Bug","description":"As reported by `bitonic` and `petermw` on `#ghc` (April 2nd):\r\n\r\n{{{\r\n07:02 < bitonic> I'm trying to get a meaningful backtrace with DWARF, using \r\n <https://ghc.haskell.org/trac/ghc/wiki/DWARF> as a guide. however, all I get is \r\n `Backtrace stopped: previous frame identical to this frame (corrupt stack?)`\r\n07:03 < bitonic> I've re-built GHC 7.10.1 using `GhcRtsHcOpts += -g` and `GhcLibHcOpts += -g`, even if \r\n I'm not sure it's even necessary\r\n07:04 < bitonic> are there any additional steps I should take? or any way to make sure that the binary \r\n I'm generating is sane?\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->7.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/10241BlockedIndefinitelyOnMVar thrown to the thread which is not blocked indefinitely2019-07-07T18:36:56ZasukamiraiBlockedIndefinitelyOnMVar thrown to the thread which is not blocked indefinitelyBlockedIndefinatelyOnMVar exception is thrown to the main thread in below source code although the thread is not blocked indefinitely.
```hs
module Main where
import qualified Control.Concurrent.MVar as MV
import qualified Control.Conc...BlockedIndefinatelyOnMVar exception is thrown to the main thread in below source code although the thread is not blocked indefinitely.
```hs
module Main where
import qualified Control.Concurrent.MVar as MV
import qualified Control.Concurrent as CC
import qualified Control.Exception as E
main :: IO ()
main = do
-- call this thread "threadA"
mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ())
mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ())
_ <- CC.forkIO $ do
-- call this thread "threadB"
MV.takeMVar mvar1 `E.catch` errorHandler1
putStrLn "after error catch"
CC.threadDelay 1000000
MV.putMVar mvar2 ()
putStrLn "after putMVar"
MV.readMVar mvar2 `E.catch` errorHandler2
putStrLn "after readMVar"
CC.threadDelay 5000000
where
errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO ()
errorHandler1 e = putStrLn $ "errorHandler1 : " ++ show e
errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO ()
errorHandler2 e = putStrLn $ "errorHandler2 : " ++ show e
```
Save above as "mvar.hs" and run by ghc as below.
```
> runhaskell mvar.hs
errorHandler1 : thread blocked indefinitely in an MVar operation
errorHandler2 : thread blocked indefinitely in an MVar operation
after error catch
after readMVar
after putMVar
```
BlockedIndefinitelyOnMVar thrown for mvar1 is correct. It will be caught by errorHandler1 and "threadB" can continue to put the value to mvar2. It means that "threadA" can wait for the value of mvar2 and it is not blocked indefinately.
However, BlockedIndefinitelyOnMVar is thrown for mvar2 on "threadA" before "threadB" puts value to the mvar2. I think it is incorrect.
----
I tested another case that adding "CC.threadDelay 10000000" before "readMVar" as below.
```hs
module Main where
import qualified Control.Concurrent.MVar as MV
import qualified Control.Concurrent as CC
import qualified Control.Exception as E
main :: IO ()
main = do
-- call this thread "threadA"
mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ())
mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ())
_ <- CC.forkIO $ do
-- call this thread "threadB"
MV.takeMVar mvar1 `E.catch` errorHandler1
putStrLn "after error catch"
CC.threadDelay 1000000
MV.putMVar mvar2 ()
putStrLn "after putMVar"
CC.threadDelay 10000000 -- <-- this line is added
MV.readMVar mvar2 `E.catch` errorHandler2
putStrLn "after readMVar"
CC.threadDelay 5000000
where
errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO ()
errorHandler1 e = putStrLn $ "errorHandler1 : " ++ show e
errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO ()
errorHandler2 e = putStrLn $ "errorHandler2 : " ++ show e
```
And it will run correctly (BlockedIndefinitelyOnMVar is not thrown for mvar2).
```
> runhaskell mvar.hs
errorHandler1 : thread blocked indefinitely in an MVar operation
after error catch
after putMVar
after readMVar
```
----
I found this behavior is same on STM / BlockedIndefinitelyOnSTM.
```hs
module Main where
import qualified Control.Concurrent.STM as STM
import qualified Control.Concurrent as CC
import qualified Control.Exception as E
main :: IO ()
main = do
tmv1 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ())
tmv2 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ())
_ <- CC.forkIO $ do
STM.atomically (STM.takeTMVar tmv1) `E.catch` errorHandler1
putStrLn "after error catch"
CC.threadDelay 1000000
STM.atomically $ STM.putTMVar tmv2 ()
putStrLn "after putTMVar"
STM.atomically (STM.readTMVar tmv2) `E.catch` errorHandler2
putStrLn "after readTMVar"
CC.threadDelay 5000000
where
errorHandler1 :: E.BlockedIndefinitelyOnSTM -> IO ()
errorHandler1 e = putStrLn $ "errorHandler1 : " ++ show e
errorHandler2 :: E.BlockedIndefinitelyOnSTM -> IO ()
errorHandler2 e = putStrLn $ "errorHandler2 : " ++ show e
```
```
> runhaskell stm.hs
errorHandler1 : thread blocked indefinitely in an STM transaction
errorHandler2 : thread blocked indefinitely in an STM transaction
after error catch
after readTMVar
after putTMVar
```
----
I tested this in below versions/OSs and got same result (exception thrown for mvar2/tmv2).
ghc7.8.3 on Windows7
ghc7.8.3 on lubuntu14.04 on VirtualBox on Windows7
ghc7.8.4 on lubuntu14.04 on VirtualBox on Windows7
ghc7.10.1 on lubuntu14.04 on VirtualBox on Windows7
Similar report #8804 found but not the same.
(In this case, the reference to the MVar is not weak)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.8.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"BlockedIndefinitelyOnMVar thrown to the thread which is not blocked indefinitely","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"simonmar"},"version":"7.8.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"BlockedIndefinatelyOnMVar exception is thrown to the main thread in below source code although the thread is not blocked indefinitely.\r\n\r\n{{{#!hs\r\nmodule Main where\r\n\r\nimport qualified Control.Concurrent.MVar as MV\r\nimport qualified Control.Concurrent as CC\r\nimport qualified Control.Exception as E\r\n\r\nmain :: IO ()\r\nmain = do\r\n -- call this thread \"threadA\"\r\n mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n _ <- CC.forkIO $ do\r\n -- call this thread \"threadB\"\r\n MV.takeMVar mvar1 `E.catch` errorHandler1\r\n putStrLn \"after error catch\"\r\n CC.threadDelay 1000000\r\n MV.putMVar mvar2 ()\r\n putStrLn \"after putMVar\"\r\n MV.readMVar mvar2 `E.catch` errorHandler2\r\n putStrLn \"after readMVar\"\r\n CC.threadDelay 5000000\r\n where\r\n errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler1 e = putStrLn $ \"errorHandler1 : \" ++ show e\r\n errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler2 e = putStrLn $ \"errorHandler2 : \" ++ show e\r\n}}}\r\n\r\nSave above as \"mvar.hs\" and run by ghc as below.\r\n\r\n{{{\r\n> runhaskell mvar.hs\r\nerrorHandler1 : thread blocked indefinitely in an MVar operation\r\nerrorHandler2 : thread blocked indefinitely in an MVar operation\r\nafter error catch\r\nafter readMVar\r\nafter putMVar\r\n}}}\r\n\r\nBlockedIndefinitelyOnMVar thrown for mvar1 is correct. It will be caught by errorHandler1 and \"threadB\" can continue to put the value to mvar2. It means that \"threadA\" can wait for the value of mvar2 and it is not blocked indefinately.\r\nHowever, BlockedIndefinitelyOnMVar is thrown for mvar2 on \"threadA\" before \"threadB\" puts value to the mvar2. I think it is incorrect.\r\n\r\n----\r\n\r\nI tested another case that adding \"CC.threadDelay 10000000\" before \"readMVar\" as below.\r\n\r\n{{{#!hs\r\nmodule Main where\r\n\r\nimport qualified Control.Concurrent.MVar as MV\r\nimport qualified Control.Concurrent as CC\r\nimport qualified Control.Exception as E\r\n\r\nmain :: IO ()\r\nmain = do\r\n -- call this thread \"threadA\"\r\n mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n _ <- CC.forkIO $ do\r\n -- call this thread \"threadB\"\r\n MV.takeMVar mvar1 `E.catch` errorHandler1\r\n putStrLn \"after error catch\"\r\n CC.threadDelay 1000000\r\n MV.putMVar mvar2 ()\r\n putStrLn \"after putMVar\"\r\n CC.threadDelay 10000000 -- <-- this line is added\r\n MV.readMVar mvar2 `E.catch` errorHandler2\r\n putStrLn \"after readMVar\"\r\n CC.threadDelay 5000000\r\n where\r\n errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler1 e = putStrLn $ \"errorHandler1 : \" ++ show e\r\n errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler2 e = putStrLn $ \"errorHandler2 : \" ++ show e\r\n}}}\r\n\r\nAnd it will run correctly (BlockedIndefinitelyOnMVar is not thrown for mvar2).\r\n\r\n{{{\r\n> runhaskell mvar.hs\r\nerrorHandler1 : thread blocked indefinitely in an MVar operation\r\nafter error catch\r\nafter putMVar\r\nafter readMVar\r\n}}}\r\n\r\n----\r\n\r\nI found this behavior is same on STM / BlockedIndefinitelyOnSTM.\r\n\r\n{{{#!hs\r\nmodule Main where\r\n\r\nimport qualified Control.Concurrent.STM as STM\r\nimport qualified Control.Concurrent as CC\r\nimport qualified Control.Exception as E\r\n\r\nmain :: IO ()\r\nmain = do\r\n tmv1 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ())\r\n tmv2 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ())\r\n _ <- CC.forkIO $ do\r\n STM.atomically (STM.takeTMVar tmv1) `E.catch` errorHandler1\r\n putStrLn \"after error catch\"\r\n CC.threadDelay 1000000\r\n STM.atomically $ STM.putTMVar tmv2 ()\r\n putStrLn \"after putTMVar\"\r\n STM.atomically (STM.readTMVar tmv2) `E.catch` errorHandler2\r\n putStrLn \"after readTMVar\"\r\n CC.threadDelay 5000000\r\n where\r\n errorHandler1 :: E.BlockedIndefinitelyOnSTM -> IO ()\r\n errorHandler1 e = putStrLn $ \"errorHandler1 : \" ++ show e\r\n errorHandler2 :: E.BlockedIndefinitelyOnSTM -> IO ()\r\n errorHandler2 e = putStrLn $ \"errorHandler2 : \" ++ show e\r\n}}}\r\n\r\n{{{\r\n> runhaskell stm.hs\r\nerrorHandler1 : thread blocked indefinitely in an STM transaction\r\nerrorHandler2 : thread blocked indefinitely in an STM transaction\r\nafter error catch\r\nafter readTMVar\r\nafter putTMVar\r\n}}}\r\n\r\n----\r\n\r\nI tested this in below versions/OSs and got same result (exception thrown for mvar2/tmv2).\r\n\r\nghc7.8.3 on Windows7\r\nghc7.8.3 on lubuntu14.04 on VirtualBox on Windows7\r\nghc7.8.4 on lubuntu14.04 on VirtualBox on Windows7\r\nghc7.10.1 on lubuntu14.04 on VirtualBox on Windows7\r\n\r\nSimilar report https://ghc.haskell.org/trac/ghc/ticket/8804 found but not the same.\r\n(In this case, the reference to the MVar is not weak)\r\n","type_of_failure":"OtherFailure","blocking":[]} -->Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/10245panic in new integer switch logic with "out-of-range" literals2019-07-07T18:36:55Zrwbartonpanic in new integer switch logic with "out-of-range" literalsCompiling this module
```
module D (f) where
f :: Int -> String
f n = case n of
0x8000000000000000 -> "yes"
_ -> "no"
```
crashes with the error
```
[1 of 1] Compiling D ( /tmp/D.hs, /tmp/D.o )
ghc-stage1: panic! (t...Compiling this module
```
module D (f) where
f :: Int -> String
f n = case n of
0x8000000000000000 -> "yes"
_ -> "no"
```
crashes with the error
```
[1 of 1] Compiling D ( /tmp/D.hs, /tmp/D.o )
ghc-stage1: panic! (the 'impossible' happened)
(GHC version 7.11.20150403 for x86_64-unknown-linux):
Map.findMin: empty map has no minimal element
```
The constant does not have to be exactly `0x8000000000000000`, everything I tested from there up to `0xffffffffffffffff` yields the same crash. Also occurs with `Word` and negative literals.
The bug seems to be tied to the target's word size somehow, though: a 64-bit compiler does not panic on `Int32` and `0x80000000`, but a 32-bit compiler does.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------ |
| Version | 7.11 |
| Type | Bug |
| TypeOfFailure | CompileTimeCrash |
| Priority | high |
| Resolution | Unresolved |
| Component | Compiler (CodeGen) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | nomeata, simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"panic in new integer switch logic with \"out-of-range\" literals","status":"New","operating_system":"","component":"Compiler (CodeGen)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.11","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["nomeata","simonmar"],"type":"Bug","description":"Compiling this module\r\n{{{\r\nmodule D (f) where\r\nf :: Int -> String\r\nf n = case n of\r\n 0x8000000000000000 -> \"yes\"\r\n _ -> \"no\"\r\n}}}\r\ncrashes with the error\r\n{{{\r\n[1 of 1] Compiling D ( /tmp/D.hs, /tmp/D.o )\r\nghc-stage1: panic! (the 'impossible' happened)\r\n (GHC version 7.11.20150403 for x86_64-unknown-linux):\r\n\tMap.findMin: empty map has no minimal element\r\n}}}\r\nThe constant does not have to be exactly `0x8000000000000000`, everything I tested from there up to `0xffffffffffffffff` yields the same crash. Also occurs with `Word` and negative literals.\r\n\r\nThe bug seems to be tied to the target's word size somehow, though: a 64-bit compiler does not panic on `Int32` and `0x80000000`, but a 32-bit compiler does.","type_of_failure":"CompileTimeCrash","blocking":[]} -->8.2.1Andreas KlebingerAndreas Klebingerhttps://gitlab.haskell.org/ghc/ghc/-/issues/10317Event manager: Multishot registrations only fire once2019-07-07T18:36:36ZBen GamariEvent manager: Multishot registrations only fire onceSince D347 the event manager has had support for multishot event registration semantics, allowing the user to receive multiple events on an fd without requiring re-registration.
Unfortunately the implementation drops the registration af...Since D347 the event manager has had support for multishot event registration semantics, allowing the user to receive multiple events on an fd without requiring re-registration.
Unfortunately the implementation drops the registration after it fires, resulting in only one callback invocation.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Event manager: Multishot registrations only fire once","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"7.10.2","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Since D347 the event manager has had support for multishot event registration semantics, allowing the user to receive multiple events on an fd without requiring re-registration.\r\n\r\nUnfortunately the implementation drops the registration after it fires, resulting in only one callback invocation.","type_of_failure":"OtherFailure","blocking":[]} -->7.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/10368STM test failing on Armhf/Linux2019-07-07T18:36:23ZerikdSTM test failing on Armhf/LinuxDuring validation on armhf/linux, I found that test T7815 had failed.
Unfortunately, it only fails intermittently on one quad core Arm board and not at all on another quad core Arm board. If I do 10 runs of the test like:
```
for x in ...During validation on armhf/linux, I found that test T7815 had failed.
Unfortunately, it only fails intermittently on one quad core Arm board and not at all on another quad core Arm board. If I do 10 runs of the test like:
```
for x in $(seq 1 10) ; do testsuite/tests/rts/T7815 50000 +RTS -N2 ; echo $? ; done
```
one will fail at least 4 or 5 times and ocassionally as many as 9 or 10 times.
The two boards are:
- Inforce Computing ifc6540 with a Qualcomm Snapdragon 805 CPU.
- Radxa Rock with a Rockchip RK3199 CPU.
The ifc6540 is the one that fails.
\@fryguybob suggests that this is actually a bug in the STM implementation that breaks on Arm because of Arm's weaker memory consistency model.8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/10380"thread blocked indefinitely" exception while blocking on a socket2019-07-07T18:36:18Ztakano-akio"thread blocked indefinitely" exception while blocking on a socketFirst start a TCP server, e.g. nc.
```
% nc localhost -l 1234 > /dev/null
```
On another shell, compile the following program and run it:
```
% ghc -threaded sock.hs
% ./sock localhost 1234
receiver: thread blocked indefinitely in an ...First start a TCP server, e.g. nc.
```
% nc localhost -l 1234 > /dev/null
```
On another shell, compile the following program and run it:
```
% ghc -threaded sock.hs
% ./sock localhost 1234
receiver: thread blocked indefinitely in an MVar operation
```
```hs
{-# LANGUAGE ViewPatterns #-}
import Control.Applicative -- GHC 7.8 compatibility
import Control.Concurrent
import qualified Control.Exception as Ex
import Control.Monad
import qualified Data.ByteString.Char8 as S
import Network.Socket
import qualified Network.Socket.ByteString as Sock
import Network.BSD (getHostByName, hostAddresses)
import System.Environment
import System.Mem
main :: IO ()
main = do
[host, read -> fromInteger -> port] <- getArgs
sock <- connectTo host port
forkVerbose "sender" $ forever $ do
_ <- Sock.send sock $ S.replicate 40000 '0'
return ()
forkVerbose "receiver" $ forever $ do
dat <- Sock.recv sock 2048
putStrLn $ "received: " ++ show dat
forever $ do
threadDelay 1000000
performGC
forkVerbose :: String -> IO () -> IO ()
forkVerbose name act = void $ forkIO $ do act; msg "exiting normally"
`Ex.catch` \e -> msg $ show (e :: Ex.SomeException)
where
msg s = putStrLn $ name ++ ": " ++ s
connectTo :: HostName -> PortNumber -> IO Socket
connectTo hostName port = do
addr <- SockAddrInet port <$> lookupHost hostName
sock <- socket AF_INET Stream 0
connect sock addr
return sock
lookupHost :: String -> IO HostAddress
lookupHost name = do
hostInfo <- getHostByName name
case hostAddresses hostInfo of
[] -> error ("Invalid host name: " ++ name)
(a:_) -> return a
```
GHC 7.8.3 doesn't have this problem.
I suspect that this is a regression in the event manager. When there is an event, `GHC.Event.Manager.onFdEvent` seems to remove all callbacks associated to the `fd`, whether or not they match the current event. In the program above, the callback for `recv` may be removed permanently when the socket becomes ready for `send`ing, causing the "receiver" thread to deadlock.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | ekmett, hvr |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"\"thread blocked indefinitely\" exception while blocking on a socket","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["ekmett","hvr"],"type":"Bug","description":"First start a TCP server, e.g. nc.\r\n\r\n{{{\r\n% nc localhost -l 1234 > /dev/null\r\n}}}\r\n\r\nOn another shell, compile the following program and run it:\r\n\r\n{{{\r\n% ghc -threaded sock.hs\r\n% ./sock localhost 1234\r\nreceiver: thread blocked indefinitely in an MVar operation\r\n}}}\r\n\r\n{{{#!hs\r\n{-# LANGUAGE ViewPatterns #-}\r\n\r\nimport Control.Applicative -- GHC 7.8 compatibility\r\nimport Control.Concurrent\r\nimport qualified Control.Exception as Ex\r\nimport Control.Monad\r\nimport qualified Data.ByteString.Char8 as S\r\nimport Network.Socket\r\nimport qualified Network.Socket.ByteString as Sock\r\nimport Network.BSD (getHostByName, hostAddresses)\r\nimport System.Environment\r\nimport System.Mem\r\n\r\nmain :: IO ()\r\nmain = do\r\n [host, read -> fromInteger -> port] <- getArgs\r\n sock <- connectTo host port\r\n forkVerbose \"sender\" $ forever $ do\r\n _ <- Sock.send sock $ S.replicate 40000 '0'\r\n return ()\r\n forkVerbose \"receiver\" $ forever $ do\r\n dat <- Sock.recv sock 2048\r\n putStrLn $ \"received: \" ++ show dat\r\n forever $ do\r\n threadDelay 1000000\r\n performGC\r\n\r\nforkVerbose :: String -> IO () -> IO ()\r\nforkVerbose name act = void $ forkIO $ do act; msg \"exiting normally\"\r\n `Ex.catch` \\e -> msg $ show (e :: Ex.SomeException)\r\n where \r\n msg s = putStrLn $ name ++ \": \" ++ s\r\n\r\nconnectTo :: HostName -> PortNumber -> IO Socket\r\nconnectTo hostName port = do\r\n addr <- SockAddrInet port <$> lookupHost hostName\r\n sock <- socket AF_INET Stream 0\r\n connect sock addr\r\n return sock\r\n\r\nlookupHost :: String -> IO HostAddress\r\nlookupHost name = do\r\n hostInfo <- getHostByName name\r\n case hostAddresses hostInfo of\r\n [] -> error (\"Invalid host name: \" ++ name)\r\n (a:_) -> return a\r\n}}}\r\n\r\nGHC 7.8.3 doesn't have this problem.\r\n\r\nI suspect that this is a regression in the event manager. When there is an event, `GHC.Event.Manager.onFdEvent` seems to remove all callbacks associated to the `fd`, whether or not they match the current event. In the program above, the callback for `recv` may be removed permanently when the socket becomes ready for `send`ing, causing the \"receiver\" thread to deadlock.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/10408The behavior of -ignore-dot-ghci and -ghci-script are weird2019-07-07T18:36:03ZZejun WuThe behavior of -ignore-dot-ghci and -ghci-script are weird```
$ for i in `seq 10`; do echo "print $i" > /tmp/$i.ghci; done
$ ghc -e 0 -ghci-script /tmp/1.ghci -ghci-script /tmp/2.ghci
2
1
0
$ ghc -e 0 -ghci-script /tmp/1.ghci -ghci-script /tmp/2.ghci -ignore-dot-ghci
0
```
`-ghci-script` are e...```
$ for i in `seq 10`; do echo "print $i" > /tmp/$i.ghci; done
$ ghc -e 0 -ghci-script /tmp/1.ghci -ghci-script /tmp/2.ghci
2
1
0
$ ghc -e 0 -ghci-script /tmp/1.ghci -ghci-script /tmp/2.ghci -ignore-dot-ghci
0
```
`-ghci-script` are executed in reverse order and are ignored when `-ignore-dot-ghci` is specified, while I expected that:
- `-ghci-script` are executed in the order they are specified;
- `-ignore-dot-ghci` only ignores the default .ghci files but still executes the scripts passed by `-ghci-script`.
I would like to change the behavior to the expected ones. But in case there are users relying on the old behavior, then it might be necessary to introduce different flags.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------- |
| Version | 7.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHCi |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | hvr, simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"The behavior of -ignore-dot-ghci and -ghci-script are weird","status":"New","operating_system":"","component":"GHCi","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"watashi"},"version":"7.10.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["hvr","simonmar"],"type":"Bug","description":"{{{\r\n$ for i in `seq 10`; do echo \"print $i\" > /tmp/$i.ghci; done\r\n$ ghc -e 0 -ghci-script /tmp/1.ghci -ghci-script /tmp/2.ghci\r\n2\r\n1\r\n0\r\n$ ghc -e 0 -ghci-script /tmp/1.ghci -ghci-script /tmp/2.ghci -ignore-dot-ghci\r\n0\r\n}}}\r\n\r\n`-ghci-script` are executed in reverse order and are ignored when `-ignore-dot-ghci` is specified, while I expected that:\r\n* `-ghci-script` are executed in the order they are specified;\r\n* `-ignore-dot-ghci` only ignores the default .ghci files but still executes the scripts passed by `-ghci-script`.\r\n\r\nI would like to change the behavior to the expected ones. But in case there are users relying on the old behavior, then it might be necessary to introduce different flags.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/10414Buggy behavior with threaded runtime (-N1 working, -N2 getting into <<loop>>)2019-07-07T18:36:02Zexio4Buggy behavior with threaded runtime (-N1 working, -N2 getting into <<loop>>)Compiling the test case with:
> ghc -O2 -threaded -eventlog -rtsopts ghc-bug.hs
Now, trying with some inputs and -N2
> $ ./ghc-bug 7 +RTS -N2
> =\> ghc-bug: \<\<loop\>\>
> $ ./ghc-bug 6 +RTS -N2
> =\> ghc-bug: \<\<loop\>\>
> $ ....Compiling the test case with:
> ghc -O2 -threaded -eventlog -rtsopts ghc-bug.hs
Now, trying with some inputs and -N2
> $ ./ghc-bug 7 +RTS -N2
> =\> ghc-bug: \<\<loop\>\>
> $ ./ghc-bug 6 +RTS -N2
> =\> ghc-bug: \<\<loop\>\>
> $ ./ghc-bug 5 +RTS -N2
> =\> 3125
> $ ./ghc-bug 5 +RTS -N2
> ghc-bug: \<\<loop\>\>
Reducing the number of capabilities to 1, it works for those inputs
> $ ./ghc-bug 7 +RTS -N1
As a side-note, the problem only happens randomly with small inputs (on my hardware), and it seems to go away with bigger inputs (the [original testcase](http://lpaste.net/132564/) felt a bit more deterministic, but I think the testcase in the ticket is good enough)
I only tested this with GHC 7.8.4 (on Debian), but people on IRC reported the same behavior with GHC 7.10.1 on OS X and Debian
Similar bug: #10218 (-fno-cse and -flate-dmd-anal didn't help with this)
```hs
import Control.Applicative
import Control.Monad
import Control.Parallel.Strategies
import System.Environment
newtype ParList a = ParList { unParList :: [a] }
nil :: ParList a
nil = ParList []
cons :: a -> ParList a -> ParList a
cons x (ParList xs) = ParList (x:xs)
instance Functor ParList where
fmap = liftM
instance Applicative ParList where
pure = return
(<*>) = ap
instance Monad ParList where
return = ParList . return
{- v code that doesn't work -}
(ParList xs) >>= f = ParList (withStrategy (parListChunk 8 rseq) (xs >>= unParList . f))
--(ParList xs) >>= f = ParList (concat (parMap rseq (unParList . f) xs))
{- ^ code that works -}
type Pair = (Int, [Int])
loop' :: Pair -> ParList Pair
loop' (size,qns) = go 1
where go n | n > size = nil
| otherwise = cons (size, n:qns) (go (n+1))
worker :: Int -> Pair -> [Pair]
worker n = unParList . go n
where go 1 = loop'
go n = loop' >=> go (n-1)
main :: IO ()
main = do
[n] <- (read <$>) <$> getArgs
print $ length (worker n (n,[]))
```8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/10444Text.Read.Lex.lex broken2019-07-07T18:35:53ZMatthew Farkas-DyckText.Read.Lex.lex broken```
Prelude> lex "&) = mempty"
[("&",") = mempty")]
Prelude> lex "∘) = mempty"
[]
```
I traced this problem to Text.Read.Lex.lex```
Prelude> lex "&) = mempty"
[("&",") = mempty")]
Prelude> lex "∘) = mempty"
[]
```
I traced this problem to Text.Read.Lex.lex8.0.1Edward KmettEdward Kmetthttps://gitlab.haskell.org/ghc/ghc/-/issues/10517Unexpected behavior of unsafeCoerce converting Word32 to Word82019-07-07T18:35:36ZsvenkUnexpected behavior of unsafeCoerce converting Word32 to Word8The function `unsafeCoerce` behaves unexpected if it is used to convert `Word32` to `Word8`:
```hs
main = do
-- prints 135
print (fromIntegral (1234567 :: Word32) :: Word8)
-- prints 1234567
print (unsafeCoerce (1234567 :: Word...The function `unsafeCoerce` behaves unexpected if it is used to convert `Word32` to `Word8`:
```hs
main = do
-- prints 135
print (fromIntegral (1234567 :: Word32) :: Word8)
-- prints 1234567
print (unsafeCoerce (1234567 :: Word32) :: Word8)
```
On the other hand coercing `Ptr Word32` to `Ptr Word8` or the other way around works perfectly fine.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Unexpected behavior of unsafeCoerce converting Word32 to Word8","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The function `unsafeCoerce` behaves unexpected if it is used to convert `Word32` to `Word8`:\r\n\r\n{{{#!hs\r\n\r\nmain = do\r\n -- prints 135\r\n print (fromIntegral (1234567 :: Word32) :: Word8)\r\n\r\n -- prints 1234567\r\n print (unsafeCoerce (1234567 :: Word32) :: Word8)\r\n}}}\r\n\r\nOn the other hand coercing `Ptr Word32` to `Ptr Word8` or the other way around works perfectly fine.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/10521Wrong results in strict Word8 storage on x642019-07-07T18:35:35ZVincentBerthoux2Wrong results in strict Word8 storage on x64The following snippet produce two different results in function of the compiler platform used:
```hs
import Data.Word( Word8 )
-- removing the bang patterns on V definition makes
-- the problem go away.
data V = V !Word8 !Word8 derivin...The following snippet produce two different results in function of the compiler platform used:
```hs
import Data.Word( Word8 )
-- removing the bang patterns on V definition makes
-- the problem go away.
data V = V !Word8 !Word8 deriving Show
toV :: Float -> V
toV d = V (truncate $ d * coeff) (fromIntegral $ exponent d + 128) where
coeff = significand d * 255.9999 / d
main :: IO ()
main =
print $ map toV [ 3.56158e-2, 0.7415215, 0.5383201, 0.1289829, 0.45520145 ]
```
On GHC 7.10.1 x86 (under windows and Linux) the output is:
```
[V 145 124,V 189 128,V 137 128,V 132 126,V 233 127]
```
On GHC 7.10.1 x64 (under windows and Linux), the (invalid) output is:
```
[V 0 124,V 0 128,V 0 128,V 0 126,V 0 127]
```
The bug appear at the following optimisation levels:
- `-O1`
- `-O2`
- `-O3`
the results are the same at `-O0`
This bug was discovered in a bug report in the library JuicyPixels [https://github.com/Twinside/Juicy.Pixels/issues/98](https://github.com/Twinside/Juicy.Pixels/issues/98).
The same problem has been seen with GHC 7.10.2 RC17.10.2rwbartonrwbartonhttps://gitlab.haskell.org/ghc/ghc/-/issues/10553powerpc: getEnvironment empty when run in GHCi2019-07-07T18:35:22ZJoachim Breitnermail@joachim-breitner.depowerpc: getEnvironment empty when run in GHCiHi,
on powerpc (only), with ghc-7.8, we have this:
```
$ cat env.hs
import System.Environment
main = getEnvironment >>= print
$ runhaskell env.hs
[]
$ ./env
[("RESET","\\e[0m")...
```
This breaks the test suite of shake. Does anyone f...Hi,
on powerpc (only), with ghc-7.8, we have this:
```
$ cat env.hs
import System.Environment
main = getEnvironment >>= print
$ runhaskell env.hs
[]
$ ./env
[("RESET","\\e[0m")...
```
This breaks the test suite of shake. Does anyone feel like investigating this?
Also tracked at https://bugs.debian.org/789458https://gitlab.haskell.org/ghc/ghc/-/issues/10629threadWaitRead throws BlockedIndefinitelyOnMVar2019-07-07T18:34:57ZFacundo DomínguezthreadWaitRead throws BlockedIndefinitelyOnMVarIn a project using the network-transport-tcp package, I'm observing `threadWaitRead` throw the exception `BlockedIndefinitelyOnMVar`.
The call stack is roughly:
```
...
n-t-tcp:Network.Transport.TCP.handleIncomingMessages
n-t-tcp:Netwo...In a project using the network-transport-tcp package, I'm observing `threadWaitRead` throw the exception `BlockedIndefinitelyOnMVar`.
The call stack is roughly:
```
...
n-t-tcp:Network.Transport.TCP.handleIncomingMessages
n-t-tcp:Network.Transport.TCP.Internal.recvInt32
n-t-tcp:Network.Transport.TCP.Internal.recvExact
network:Network.Socket.ByteString:recv
network:Network.Socket.ByteString:recvInner
network:Network.Socket.Internal:throwSocketErrorWaitRead
base:Control.Concurrent:threadWaitRead
```
IIUC this would be an RTS bug. The socket file descriptor is healthy and works fine if the exception is caught and `threadWaitRead` is retried.
Unfortunately, I can only reproduce this in a particular cluster and with a rather complex test case while using the threaded runtime.
I'd appreciate any advice on inspecting the RTS code to scan for the cause of `BlockedIndefinitelyOnMVar` being thrown.
Of course, if someone can help explaining this behavior I'll be most thankful.Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/10639Tight (non-allocating) loop freezes the scheduler2019-07-07T18:34:55Zgizmo.mk0Tight (non-allocating) loop freezes the schedulerHere is a program that spawns a thread from the main thread, which tries to constantly write out a message to the console.
```hs
module Main where
import Control.Concurrent (forkIO)
main :: IO ()
main = do
_ <- forkIO $ runForever...Here is a program that spawns a thread from the main thread, which tries to constantly write out a message to the console.
```hs
module Main where
import Control.Concurrent (forkIO)
main :: IO ()
main = do
_ <- forkIO $ runForever $ putStrLn "Hey"
runForever $ return ()
runForever :: IO () -> IO ()
runForever action = action >> runForever action
```
If you compile it with 'ghc main', it works correctly - it prints out the message continuously, and you can terminate it by pressing Ctrl-C. However, if you compile it with 'ghc -O main' (or -O2, or -O3...), it doesn't print out anything, and the only way to exit is to kill the process from Task Manager.
This was reproducable with GHC 7.10.1, on a Windows 7 x64 machine, with an AMD A4-5300 APU.
''EDIT: As it turns out, using "yield" instead of "return ()" solves the problem. It seems I misunderstood how forkIO works. However, I'm not sure if the current working is intentional or not, so I think I should leave this ticket open - just to be on the safe side.''https://gitlab.haskell.org/ghc/ghc/-/issues/10688Incorrect program produced, different result with equivalent code2019-07-07T18:34:39ZIdeophageIncorrect program produced, different result with equivalent codeedit :
Actually, I realized that this is not a bug. This is due to the lack of type signatures in my program. I thought that was a bug because sometimes the program used `Int`s, sometimes `Integer`s, and just expanding a definition can c...edit :
Actually, I realized that this is not a bug. This is due to the lack of type signatures in my program. I thought that was a bug because sometimes the program used `Int`s, sometimes `Integer`s, and just expanding a definition can change this (see the code in attachment). I apologize for opening a ticket for that (I thought `Integer`s were used since it is the case in ghci).
Below my original message.
The program enters an infinite loop (100% cpu, not stopping) because it fails to recognize the stopping condition of a `takeWhile`. If we make the list finite, it takes all the elements while it should stop before.
I don't know how to simplify the code since if I change it a little (e.g. by replacing the name of an object by its definition), sometimes it works well, sometimes not.
When I enter the code in ghci, it works well but not when compiled.
I don't know if I should explain what the code was for initially, tell me.https://gitlab.haskell.org/ghc/ghc/-/issues/10691certain operations in new integer-gmp are too lazy2019-07-07T18:34:38Zrwbartoncertain operations in new integer-gmp are too lazyThis came up in \#ghc the other day.
```
rwbarton@morphism:~$ ghci-7.10.1
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Prelude> undefined * 0
0
```
For consistency not just with `Int`, but also other integer-\* implem...This came up in \#ghc the other day.
```
rwbarton@morphism:~$ ghci-7.10.1
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Prelude> undefined * 0
0
```
For consistency not just with `Int`, but also other integer-\* implementations, this should be undefined.
Also affected is for example `andInteger`.8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/10754truncate /= double2Int2019-07-07T18:34:10ZYuriy Syrovetskiytruncate /= double2IntThere is a rule in libraries/base/GHC/Float.hs:
```hs
"truncate/Double->Int" truncate = double2Int
```
But it is not true for some values. Particularly,
```hs
let infinity = 1/0 :: Double
truncate infinity :: Int == 0
double2Int infi...There is a rule in libraries/base/GHC/Float.hs:
```hs
"truncate/Double->Int" truncate = double2Int
```
But it is not true for some values. Particularly,
```hs
let infinity = 1/0 :: Double
truncate infinity :: Int == 0
double2Int infinity == -9223372036854775808 -- minBound
```
As a result, the value of `truncate (1/0 :: Double) :: Int` depends on optimization level.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.10.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"truncate /= double2Int","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.2","keywords":["double2Int,","rewrite,","rule","truncate,"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"There is a rule in libraries/base/GHC/Float.hs:\r\n{{{#!hs\r\n\"truncate/Double->Int\" truncate = double2Int\r\n}}}\r\nBut it is not true for some values. Particularly,\r\n{{{#!hs\r\nlet infinity = 1/0 :: Double\r\ntruncate infinity :: Int == 0\r\ndouble2Int infinity == -9223372036854775808 -- minBound\r\n}}}\r\n\r\nAs a result, the value of {{{truncate (1/0 :: Double) :: Int}}} depends on optimization level.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/10891`reify` doesn't find associated type families2019-07-07T18:33:11Zantalsz`reify` doesn't find associated type familiesTemplate Haskell's `reify` doesn't find the the associated type families of a type class. Consider the following two classes:
```hs
class C a where
f :: a -> Int
class C' a where
type F a :: *
f' :: a -> Int
```
These produce id...Template Haskell's `reify` doesn't find the the associated type families of a type class. Consider the following two classes:
```hs
class C a where
f :: a -> Int
class C' a where
type F a :: *
f' :: a -> Int
```
These produce identical, up to renaming, output when passed to `reify`:
```hs
-- putStrLn $(stringE . show =<< reify ''C)
ClassI (ClassD [] Ghci1.C [PlainTV a_1627398388] []
[SigD Ghci1.f
(ForallT [PlainTV a_1627398388]
[ClassP Ghci1.C [VarT a_1627398388]]
(AppT (AppT ArrowT (VarT a_1627398388))
(ConT GHC.Types.Int)))])
[]
-- putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
[SigD Ghci3.f'
(ForallT [PlainTV a_1627405973]
[ClassP Ghci3.C' [VarT a_1627405973]]
(AppT (AppT ArrowT (VarT a_1627405973))
(ConT GHC.Types.Int)))])
[]
```
If I know the name of `F`, I can look up information about it:
```hs
-- putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
```
But I can't find the name of `F` in the first place. Even if I add an instance of the type class, the `InstanceD` has none of the information about the definition. Given
```hs
instance C' [a] where
type F [a] = a
f' = length
```
we get
```hs
-- putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
[SigD Ghci3.f'
(ForallT [PlainTV a_1627405973]
[ClassP Ghci3.C' [VarT a_1627405973]]
(AppT (AppT ArrowT (VarT a_1627405973))
(ConT GHC.Types.Int)))])
[InstanceD []
(AppT (ConT Ghci3.C')
(AppT ListT (VarT a_1627406161)))
[]]
```
This problem was confirmed to exist in the following configurations:
- GHC 7.10.2 with version 2.10.0.0 of the template-haskell package.
- GHC 7.8.3 with version 2.9.0.0 of the template-haskell package.
- GHC 7.4.2 with version 2.7.0.0 of the template-haskell package.
(I also posted this on Stack Overflow in //2013//, where it has been languishing ever since: http://stackoverflow.com/q/17247880/237428.)8.0.1Ömer Sinan AğacanÖmer Sinan Ağacanhttps://gitlab.haskell.org/ghc/ghc/-/issues/10940Random number chosen by openTempFile is always 18042893838469308862019-07-07T18:32:58ZAnders KaseorgRandom number chosen by openTempFile is always 1804289383846930886```hs
import System.Directory
import System.IO
main = do
(p, _) <- openTempFile "/tmp" ""
print p
removeFile p
```
```console
$ runghc temp.hs
"/tmp/1804289383846930886"
$ runghc temp.hs
"/tmp/1804289383846930886"
$ runghc temp.hs...```hs
import System.Directory
import System.IO
main = do
(p, _) <- openTempFile "/tmp" ""
print p
removeFile p
```
```console
$ runghc temp.hs
"/tmp/1804289383846930886"
$ runghc temp.hs
"/tmp/1804289383846930886"
$ runghc temp.hs
"/tmp/1804289383846930886"
$ runghc temp.hs
"/tmp/1804289383846930886"
```
This “random” number is the concatenation of the first two numbers 1804289383, 846930886 returned by glibc’s `rand()` when not seeded (or seeded with 1).
This is not immediately a library security bug, I think: the file is created with `O_EXCL`, and if it already exists, `openTempFile` will move onto the next value 16816927771714636915, and so on. However, the predictable filenames make a potential application security bug that much more likely.
(For your amusement, [Google 1804289383846930886](https://www.google.com/search?q=1804289383846930886).)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.10.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Random number chosen by openTempFile is always 1804289383846930886","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{#!hs\r\nimport System.Directory\r\nimport System.IO\r\nmain = do\r\n (p, _) <- openTempFile \"/tmp\" \"\"\r\n print p\r\n removeFile p\r\n}}}\r\n\r\n{{{#!console\r\n$ runghc temp.hs\r\n\"/tmp/1804289383846930886\"\r\n$ runghc temp.hs\r\n\"/tmp/1804289383846930886\"\r\n$ runghc temp.hs\r\n\"/tmp/1804289383846930886\"\r\n$ runghc temp.hs\r\n\"/tmp/1804289383846930886\"\r\n}}}\r\n\r\nThis “random” number is the concatenation of the first two numbers 1804289383, 846930886 returned by glibc’s `rand()` when not seeded (or seeded with 1).\r\n\r\nThis is not immediately a library security bug, I think: the file is created with `O_EXCL`, and if it already exists, `openTempFile` will move onto the next value 16816927771714636915, and so on. However, the predictable filenames make a potential application security bug that much more likely.\r\n\r\n(For your amusement, [https://www.google.com/search?q=1804289383846930886 Google 1804289383846930886].)","type_of_failure":"OtherFailure","blocking":[]} -->Ben GamariBen Gamarihttps://gitlab.haskell.org/ghc/ghc/-/issues/11001BlockedIndefinitelyOnMVar thrown with live reference in unrelated finalizer2019-07-07T18:32:43ZexFalsoBlockedIndefinitelyOnMVar thrown with live reference in unrelated finalizerI am not sure whether this is a bug, but it is certainly unexpected behaviour. The following code throws a BlockedIndefinitelyOnMVar in the forked thread even though the MVar would be eventually written to by an unrelated finalizer:
```...I am not sure whether this is a bug, but it is certainly unexpected behaviour. The following code throws a BlockedIndefinitelyOnMVar in the forked thread even though the MVar would be eventually written to by an unrelated finalizer:
```hs
import Control.Concurrent
import Data.IORef
main :: IO ()
main = do
mvar <- newEmptyMVar
-- _ <- forkIO $ threadDelay 9999999999999 >> isEmptyMVar mvar >> return ()
ref <- newIORef () -- unrelated IORef
_ <- mkWeakIORef ref (putMVar mvar ()) -- register finalizer
_ <- forkFinally (takeMVar mvar :: IO ()) print
threadDelay 1000000
```
And indeed, if the forkIO line is uncommented no exception is thrown, as the new thread keeps another live reference to the MVar. Is this intended behaviour? Why does the MVar reference in the finalizer not count for BlockedIndefinitelyOnMVar?
(A similar thing happens with STM primitives.)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.10.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"BlockedIndefinitelyOnMVar thrown with live reference in unrelated finalizer","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.2","keywords":["BlockedIndefinitelyOnMVar","finalize"],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"I am not sure whether this is a bug, but it is certainly unexpected behaviour. The following code throws a BlockedIndefinitelyOnMVar in the forked thread even though the MVar would be eventually written to by an unrelated finalizer:\r\n\r\n{{{#!hs\r\nimport Control.Concurrent\r\nimport Data.IORef\r\n\r\nmain :: IO ()\r\nmain = do\r\n mvar <- newEmptyMVar\r\n -- _ <- forkIO $ threadDelay 9999999999999 >> isEmptyMVar mvar >> return ()\r\n ref <- newIORef () -- unrelated IORef\r\n _ <- mkWeakIORef ref (putMVar mvar ()) -- register finalizer\r\n _ <- forkFinally (takeMVar mvar :: IO ()) print\r\n threadDelay 1000000\r\n}}}\r\n\r\nAnd indeed, if the forkIO line is uncommented no exception is thrown, as the new thread keeps another live reference to the MVar. Is this intended behaviour? Why does the MVar reference in the finalizer not count for BlockedIndefinitelyOnMVar?\r\n\r\n(A similar thing happens with STM primitives.)","type_of_failure":"OtherFailure","blocking":[]} -->