GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:51:57Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/6145DataCon do not have location info2019-07-07T18:51:57ZJeanPhilippeMoresmauDataCon do not have location infoA data constructor does not have a valid source location associated with it in the API.
The sample code attached will print True in 7.0.4 and False in 7.4.1, because no valid srcspan is attached to the DataCon.
This is a problem for seve...A data constructor does not have a valid source location associated with it in the API.
The sample code attached will print True in 7.0.4 and False in 7.4.1, because no valid srcspan is attached to the DataCon.
This is a problem for several EclipseFP/BuildWrapper operations that rely on srcspan being right...
I've notified the mailing list of the issue, and Simon Peyton Jones was kind enough to fix it without an issue, but I wanted to create it, hopefully I'll try the next nightly release:
```
commit cb705a38d677e2ab4cad37447c8180bd397d5576
Author: Simon Peyton Jones <simonpj@microsoft.com>
Date: Tue Jun 5 13:35:07 2012 +0100
Add sensible locations to record-selector bindings
compiler/typecheck/TcTyClsDecls.lhs | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)
```https://gitlab.haskell.org/ghc/ghc/-/issues/6139Data.Time.Day read instance too liberal2019-07-07T18:51:59ZguestData.Time.Day read instance too liberalPrelude Data.Time\> read "0001-22-01" :: Day
0001-12-01
Obviously, this should be a parse error.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Versi...Prelude Data.Time\> read "0001-22-01" :: Day
0001-12-01
Obviously, this should be a parse error.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.0.3 |
| 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":"Data.Time.Day read instance too liberal","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Prelude Data.Time> read \"0001-22-01\" :: Day\r\n0001-12-01\r\n\r\nObviously, this should be a parse error.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/6131-fprof-auto adds cost centers to INLINE functions2019-07-07T18:52:01Ztakano-akio-fprof-auto adds cost centers to INLINE functionsAccording to the Section 5.2 of User's Guide, -fprof-auto should add cost centers only to functions that are not marked INLINE. However GHC 7.4 doesn't respect this.
A simple example:
```
foo :: Integer -> Integer
foo x = x + 100
{-# I...According to the Section 5.2 of User's Guide, -fprof-auto should add cost centers only to functions that are not marked INLINE. However GHC 7.4 doesn't respect this.
A simple example:
```
foo :: Integer -> Integer
foo x = x + 100
{-# INLINE foo #-}
main = print $ loop (10000000::Int) 10000000000000000000000
where
loop 0 x = x
loop n x = loop (n-1) (foo x)
```
Compile and run this like:
```
% ghc -prof -fprof-auto -O2 test.hs
% ./test +RTS -p
% grep foo test.prof
```
And you will see 'foo' is listed as a cost center.
This happens with GHC 7.4.1 and 7.4.2-rc1
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.4.2-rc1 |
| 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":"-fprof-auto adds cost centers to INLINE functions","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2-rc1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"According to the Section 5.2 of User's Guide, -fprof-auto should add cost centers only to functions that are not marked INLINE. However GHC 7.4 doesn't respect this.\r\n\r\nA simple example:\r\n\r\n{{{\r\nfoo :: Integer -> Integer\r\nfoo x = x + 100\r\n{-# INLINE foo #-}\r\n\r\nmain = print $ loop (10000000::Int) 10000000000000000000000\r\n where\r\n loop 0 x = x\r\n loop n x = loop (n-1) (foo x)\r\n}}}\r\n\r\nCompile and run this like:\r\n\r\n{{{\r\n% ghc -prof -fprof-auto -O2 test.hs\r\n% ./test +RTS -p\r\n% grep foo test.prof\r\n}}}\r\n\r\nAnd you will see 'foo' is listed as a cost center.\r\n\r\nThis happens with GHC 7.4.1 and 7.4.2-rc1","type_of_failure":"OtherFailure","blocking":[]} -->7.4.3https://gitlab.haskell.org/ghc/ghc/-/issues/6130Weak pointer to MVar is finalized, even though MVar is still accessible2019-07-07T18:52:01ZjmillikinWeak pointer to MVar is finalized, even though MVar is still accessibleI'm seeing a problem mixing MVar and Weak: even though the MVar is still accessible from a function's scope (and the main thread is blocking on it), the Weak thinks it should be finalized.
Only seems to happen when compiled with -O2.
P...I'm seeing a problem mixing MVar and Weak: even though the MVar is still accessible from a function's scope (and the main thread is blocking on it), the Weak thinks it should be finalized.
Only seems to happen when compiled with -O2.
Platform: 64-bit Linux
Reproduced with GHC versions: 6.10.4, 6.12.3, 7.0.4, 7.2.2, 7.4.1
```
module Main (main) where
import Control.Concurrent
import Control.Monad (forever, forM_)
import Data.IORef
import System.Mem
import System.Mem.Weak
dispatchPendingCalls :: IORef [Weak (MVar ())] -> IO ()
dispatchPendingCalls ref = forever $ do
threadDelay 100000
pending <- atomicModifyIORef ref (\p -> ([], p))
forM_ pending (\weak -> do
maybeMVar <- deRefWeak weak
case maybeMVar of
Just mvar -> putMVar mvar ()
Nothing -> putStrLn "dispatchReply: weak mvar is Nothing")
call :: IORef [Weak (MVar ())] -> IO ()
call ref = do
mvar <- newEmptyMVar
weak <- mkWeakPtr mvar (Just (putStrLn "call: finalising weak"))
putStrLn "call: about to insert weak into list"
atomicModifyIORef ref (\p -> (weak : p, ()))
putStrLn "call: inserted weak into list"
performGC
takeMVar mvar
putStrLn "call: took from mvar"
main :: IO ()
main = do
pendingCalls <- newIORef []
_ <- forkIO (dispatchPendingCalls pendingCalls)
call pendingCalls
```
Expected output:
```
$ ghc --make WeakVar.hs
$ ./WeakMvar
call: about to insert weak into list
call: inserted weak into list
call: took from mvar
```
Actual output:
```
$ ghc --make -O2 WeakVar.hs
$ ./WeakMvar
call: about to insert weak into list
call: inserted weak into list
call: finalizing weak
dispatchReply: weak mvar is Nothing
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.4.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":"Weak pointer to MVar is finalized, even though MVar is still accessible","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I'm seeing a problem mixing MVar and Weak: even though the MVar is still accessible from a function's scope (and the main thread is blocking on it), the Weak thinks it should be finalized.\r\n\r\nOnly seems to happen when compiled with -O2.\r\n\r\nPlatform: 64-bit Linux\r\nReproduced with GHC versions: 6.10.4, 6.12.3, 7.0.4, 7.2.2, 7.4.1\r\n\r\n{{{\r\nmodule Main (main) where\r\n\r\nimport Control.Concurrent\r\nimport Control.Monad (forever, forM_)\r\nimport Data.IORef\r\nimport System.Mem\r\nimport System.Mem.Weak\r\n\r\ndispatchPendingCalls :: IORef [Weak (MVar ())] -> IO ()\r\ndispatchPendingCalls ref = forever $ do\r\n\tthreadDelay 100000\r\n\t\r\n\tpending <- atomicModifyIORef ref (\\p -> ([], p))\r\n\tforM_ pending (\\weak -> do\r\n\t\tmaybeMVar <- deRefWeak weak\r\n\t\tcase maybeMVar of\r\n\t\t\tJust mvar -> putMVar mvar ()\r\n\t\t\tNothing -> putStrLn \"dispatchReply: weak mvar is Nothing\")\r\n\r\ncall :: IORef [Weak (MVar ())] -> IO ()\r\ncall ref = do\r\n\tmvar <- newEmptyMVar\r\n\tweak <- mkWeakPtr mvar (Just (putStrLn \"call: finalising weak\"))\r\n\t\r\n\tputStrLn \"call: about to insert weak into list\"\r\n\tatomicModifyIORef ref (\\p -> (weak : p, ()))\r\n\tputStrLn \"call: inserted weak into list\"\r\n\tperformGC\r\n\ttakeMVar mvar\r\n\tputStrLn \"call: took from mvar\"\r\n\r\nmain :: IO ()\r\nmain = do\r\n\tpendingCalls <- newIORef []\r\n\t_ <- forkIO (dispatchPendingCalls pendingCalls)\r\n\tcall pendingCalls\r\n}}}\r\n\r\nExpected output:\r\n{{{\r\n$ ghc --make WeakVar.hs\r\n$ ./WeakMvar\r\ncall: about to insert weak into list\r\ncall: inserted weak into list\r\ncall: took from mvar\r\n}}}\r\n\r\nActual output:\r\n{{{\r\n$ ghc --make -O2 WeakVar.hs\r\n$ ./WeakMvar\r\ncall: about to insert weak into list\r\ncall: inserted weak into list\r\ncall: finalizing weak\r\ndispatchReply: weak mvar is Nothing\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/6128ghc 7.4.2 does not work with LDAP-0.6.62019-07-07T18:52:01Zmagicloudghc 7.4.2 does not work with LDAP-0.6.6Sample code as below. When I ghci/runhaskell/ghc (compile) it with ghc 7.2.2. Everything is fine.
But when I use ghc 7.4.1, only ghci/runhaskell works. ghc compiled (without any extra parameters) binary always failed at the second ldap o...Sample code as below. When I ghci/runhaskell/ghc (compile) it with ghc 7.2.2. Everything is fine.
But when I use ghc 7.4.1, only ghci/runhaskell works. ghc compiled (without any extra parameters) binary always failed at the second ldap operation with message: LDAP error: ldapSimpleBind: LDAPException LdapServerDown(-1): Can't contact LDAP server. I am sure there is nothing wrong with the network, the client library, or the server/service. Trying to capture the network package, it seemed that the program did not open a network connection at all.
Code:
ldap \<- ldapInit domain ldapPort
> ldapSimpleBind ldap bindDN bindPW
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.4.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":"ghc 7.4.1 does not work with LDAP-0.6.6","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":["LDAP"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Sample code as below. When I ghci/runhaskell/ghc (compile) it with ghc 7.2.2. Everything is fine.\r\nBut when I use ghc 7.4.1, only ghci/runhaskell works. ghc compiled (without any extra parameters) binary always failed at the second ldap operation with message: LDAP error: ldapSimpleBind: LDAPException LdapServerDown(-1): Can't contact LDAP server. I am sure there is nothing wrong with the network, the client library, or the server/service. Trying to capture the network package, it seemed that the program did not open a network connection at all.\r\n\r\nCode:\r\n ldap <- ldapInit domain ldapPort\r\n ldapSimpleBind ldap bindDN bindPW","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/6117Cyclic Type Class Hierarchy Produces <<loop>>2019-07-07T18:52:05Zjun0Cyclic Type Class Hierarchy Produces <<loop>>If there is a cyclic class hierarchy like
```
class B a => Semigroup a where ...[[BR]]
class Semigroup (Additive a) => Ring a where ...[[BR]]
instance Ring a => Semigroup (Additive a) where ...[[BR]]
```
...If there is a cyclic class hierarchy like
```
class B a => Semigroup a where ...[[BR]]
class Semigroup (Additive a) => Ring a where ...[[BR]]
instance Ring a => Semigroup (Additive a) where ...[[BR]]
```
then uses of B's methods on `(Additive a)` in the method implementations of the
third declaration `instance Ring a => Semigroup (Additive a)` will:
1. be accepted by the compiler even in cases where `B (Additive a)` is not derivable.
1. result in \<\<loop\>\>.
The attached program prints \<\<loop\>\> when compiled with GHC-7.2.1 or newer but prints 1234567890 when compiled with GHC-7.0.4 or older. I haven't had time to try out any revisions in between those two, but I did check that HEAD produces \<\<loop\>\> as well.7.8.1Simon Peyton JonesSimon Peyton Joneshttps://gitlab.haskell.org/ghc/ghc/-/issues/6116ctrl-c doesn't always work when entering text in ghci2019-07-07T18:52:06Zjudahjctrl-c doesn't always work when entering text in ghciWith ghci-7.5.20120519 (on Mac and probably also Linux): type some text, then press ctrl-c. Then type more text, and press ctrl-c again. The first time you press ctrl-c, it starts a new line. But the second time you press ctrl-c, nothing...With ghci-7.5.20120519 (on Mac and probably also Linux): type some text, then press ctrl-c. Then type more text, and press ctrl-c again. The first time you press ctrl-c, it starts a new line. But the second time you press ctrl-c, nothing happens. (Actually running code from within ghci resets this process.)
This is a regression from the behavior of ghci-7.4.1, where every time you press ctrl-C it caused a new line to be printed.
From my initial investigation, I think this was caused by ghc commit 206c8fc3ebd64c40ae09742fdea09ffd0f915d5c, which was used to fix #2786.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.5 |
| 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":"ctrl-c doesn't always work when entering text in ghci","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.5","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"With ghci-7.5.20120519 (on Mac and probably also Linux): type some text, then press ctrl-c. Then type more text, and press ctrl-c again. The first time you press ctrl-c, it starts a new line. But the second time you press ctrl-c, nothing happens. (Actually running code from within ghci resets this process.)\r\n\r\nThis is a regression from the behavior of ghci-7.4.1, where every time you press ctrl-C it caused a new line to be printed.\r\n\r\nFrom my initial investigation, I think this was caused by ghc commit 206c8fc3ebd64c40ae09742fdea09ffd0f915d5c, which was used to fix #2786. ","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/6098debugger does not know the correct type for a newtype field2021-06-28T18:58:02Zphercekdebugger does not know the correct type for a newtype fieldThis bug is in 7.4.1. I think it was also in 7.0.3. It is also in the current head:\[\[BR\]\]
commit 921530b477867edb5158e4ad5bbbdb5c7c531c97\[\[BR\]\]
Date: Tue May 15 10:32:58 2012 +0100
Here is the console log. Notice that the type o...This bug is in 7.4.1. I think it was also in 7.0.3. It is also in the current head:\[\[BR\]\]
commit 921530b477867edb5158e4ad5bbbdb5c7c531c97\[\[BR\]\]
Date: Tue May 15 10:32:58 2012 +0100
Here is the console log. Notice that the type of allItems is resolved as TWrapper but it should be \[Int\]. Expressions in conditional breakpoints are failing because of this.
```
18:06 tm=3:2 st=0 peter@phnm ~/haskell/ghc-working/inplace/lib
1035> cat bindings-bug.hs
newtype TWrapper = Wrapper
{ mItems :: [Int]
} deriving Show
main = print $ test $ Wrapper [1]
test Wrapper{ mItems = allItems } = id $
let headItem = head allItems in
headItem
18:06 tm=0 st=0 peter@phnm ~/haskell/ghc-working/inplace/lib
1036> ../../ghc/stage2/build/tmp/ghc-stage2 -B. --interactive bindings-bug.hs
GHCi, version 7.5.20120515: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( bindings-bug.hs, interpreted )
Ok, modules loaded: Main.
*Main> :break 7 37
Breakpoint 0 activated at bindings-bug.hs:(7,37)-(9,10)
*Main> :main
Stopped at bindings-bug.hs:(7,37)-(9,10)
_result :: Int = _
allItems :: TWrapper = _
[bindings-bug.hs:(7,37)-(9,10)] *Main> :list
6
vv
7 test Wrapper{ mItems = allItems } = id $
8 let headItem = head allItems in
9 headItem
^^
10
[bindings-bug.hs:(7,37)-(9,10)] *Main> head allItems
<interactive>:5:6:
Couldn't match expected type `[a0]' with actual type `TWrapper'
In the first argument of `head', namely `allItems'
In the expression: head allItems
In an equation for `it': it = head allItems
[bindings-bug.hs:(7,37)-(9,10)] *Main> :continue
1
*Main> :quit
Leaving GHCi.
18:06 tm=42 st=0 peter@phnm ~/haskell/ghc-working/inplace/lib
1037>
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.5 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHCi |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Linux |
| Architecture | x86_64 (amd64) |
</details>
<!-- {"blocked_by":[],"summary":"debugger does not know the correct type for a newtype field","status":"New","operating_system":"Linux","component":"GHCi","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.5","keywords":["bindings","debugger"],"differentials":[],"test_case":"","architecture":"x86_64 (amd64)","cc":[""],"type":"Bug","description":"This bug is in 7.4.1. I think it was also in 7.0.3. It is also in the current head:[[BR]]\r\ncommit 921530b477867edb5158e4ad5bbbdb5c7c531c97[[BR]]\r\nDate: Tue May 15 10:32:58 2012 +0100\r\n\r\nHere is the console log. Notice that the type of allItems is resolved as TWrapper but it should be [Int]. Expressions in conditional breakpoints are failing because of this.\r\n\r\n\r\n{{{\r\n18:06 tm=3:2 st=0 peter@phnm ~/haskell/ghc-working/inplace/lib\r\n1035> cat bindings-bug.hs\r\nnewtype TWrapper = Wrapper\r\n { mItems :: [Int]\r\n } deriving Show\r\n\r\nmain = print $ test $ Wrapper [1]\r\n\r\ntest Wrapper{ mItems = allItems } = id $\r\n let headItem = head allItems in\r\n headItem\r\n\r\n18:06 tm=0 st=0 peter@phnm ~/haskell/ghc-working/inplace/lib\r\n1036> ../../ghc/stage2/build/tmp/ghc-stage2 -B. --interactive bindings-bug.hs\r\nGHCi, version 7.5.20120515: http://www.haskell.org/ghc/ :? for help\r\nLoading package ghc-prim ... linking ... done.\r\nLoading package integer-gmp ... linking ... done.\r\nLoading package base ... linking ... done.\r\n[1 of 1] Compiling Main ( bindings-bug.hs, interpreted )\r\nOk, modules loaded: Main.\r\n*Main> :break 7 37\r\nBreakpoint 0 activated at bindings-bug.hs:(7,37)-(9,10)\r\n*Main> :main \r\nStopped at bindings-bug.hs:(7,37)-(9,10)\r\n_result :: Int = _\r\nallItems :: TWrapper = _\r\n[bindings-bug.hs:(7,37)-(9,10)] *Main> :list\r\n6 \r\n vv\r\n7 test Wrapper{ mItems = allItems } = id $\r\n8 let headItem = head allItems in\r\n9 headItem\r\n ^^\r\n10 \r\n[bindings-bug.hs:(7,37)-(9,10)] *Main> head allItems\r\n\r\n<interactive>:5:6:\r\n Couldn't match expected type `[a0]' with actual type `TWrapper'\r\n In the first argument of `head', namely `allItems'\r\n In the expression: head allItems\r\n In an equation for `it': it = head allItems\r\n[bindings-bug.hs:(7,37)-(9,10)] *Main> :continue \r\n1\r\n*Main> :quit \r\nLeaving GHCi.\r\n18:06 tm=42 st=0 peter@phnm ~/haskell/ghc-working/inplace/lib\r\n1037> \r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/6057hGetBufNonBlocking blocks the underlying handle on Windows2019-07-07T18:52:23ZcetinserthGetBufNonBlocking blocks the underlying handle on WindowsIn a cross-platform transport-layer proxy software I am developing, I have this piece of code:
```
a >- b $ j -- forks
b >- a $ j -- forks
```
where a and b are handles; j is an exception handler and (\>-) is a self-for...In a cross-platform transport-layer proxy software I am developing, I have this piece of code:
```
a >- b $ j -- forks
b >- a $ j -- forks
```
where a and b are handles; j is an exception handler and (\>-) is a self-forking infinite loop IO that splices data between two handles, defined previously in terms of hGetBufSome and and hPutBuf on Windows.
I just noticed that:
```
b >- a $ j -- forks
a >- b $ j -- forks
```
behaves differently from:
```
a >- b $ j -- forks
b >- a $ j -- forks
```
When proxying connections to an SSH server the first one does not show the greeting from the SSH server before receiving user input, the second does show the greeting.
As the two lines immediately fork to their own Haskell threads the blocking must come from the underlying handles.
When I attempted to use hGetBufNonBlocking to avoid the problem I noticed that the docs read: "NOTE: on Windows, this function does not work correctly; it behaves identically to hGetBuf.".
The reason I chose to use handles in the first place was the "Improving I/O Performance over sockets" section in the network package: http://hackage.haskell.org/packages/archive/network/2.3.0.13/doc/html/Network.html.
At this point I am stuck as neither the network package exports functions that work on pointers to pre-allocated memory buffers nor the h---- famiy of functions from System.IO behave as their names suggest.
Defining (\>-) in terms of recv and sendAll from Network.Socket.ByteString does show the problem and both variants behave exactly the same at run time and this is the only correct behaviour as I have no way of knowing or special-casing which application layer protocols expect initiation from which end (client input first or server greeting first).
I am reporting this issue to both here and to the maintainers of the network package on GitHub .
This bug is reported for 7.0.4 but I highly suspect the behavior may still be the same with newer GHC versions.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.0.4 |
| 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":"hGetBufNonBlocking blocks the underlying handle on Windows","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.4","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"In a cross-platform transport-layer proxy software I am developing, I have this piece of code:\r\n\r\n\r\n{{{\r\n a >- b $ j -- forks\r\n b >- a $ j -- forks\r\n}}}\r\n\r\nwhere a and b are handles; j is an exception handler and (>-) is a self-forking infinite loop IO that splices data between two handles, defined previously in terms of hGetBufSome and and hPutBuf on Windows.\r\n\r\nI just noticed that:\r\n\r\n\r\n{{{\r\n b >- a $ j -- forks\r\n a >- b $ j -- forks\r\n}}}\r\n\r\nbehaves differently from:\r\n\r\n\r\n{{{\r\n a >- b $ j -- forks\r\n b >- a $ j -- forks\r\n}}}\r\n\r\nWhen proxying connections to an SSH server the first one does not show the greeting from the SSH server before receiving user input, the second does show the greeting.\r\n\r\nAs the two lines immediately fork to their own Haskell threads the blocking must come from the underlying handles.\r\n\r\nWhen I attempted to use hGetBufNonBlocking to avoid the problem I noticed that the docs read: \"NOTE: on Windows, this function does not work correctly; it behaves identically to hGetBuf.\".\r\n\r\nThe reason I chose to use handles in the first place was the \"Improving I/O Performance over sockets\" section in the network package: http://hackage.haskell.org/packages/archive/network/2.3.0.13/doc/html/Network.html.\r\n\r\nAt this point I am stuck as neither the network package exports functions that work on pointers to pre-allocated memory buffers nor the h---- famiy of functions from System.IO behave as their names suggest.\r\n\r\nDefining (>-) in terms of recv and sendAll from Network.Socket.ByteString does show the problem and both variants behave exactly the same at run time and this is the only correct behaviour as I have no way of knowing or special-casing which application layer protocols expect initiation from which end (client input first or server greeting first).\r\n\r\nI am reporting this issue to both here and to the maintainers of the network package on GitHub .\r\n\r\nThis bug is reported for 7.0.4 but I highly suspect the behavior may still be the same with newer GHC versions.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/6046inconsistent type error messages between ghc and ghci2019-07-07T18:52:25ZCarter Schonwaldinconsistent type error messages between ghc and ghciWhen building syb 0.3.6 with todays head / 7.5
I get different type error messages for the module Data/Generics/Twins.hs
respectively from ghc when doing cabal install syb vs when i load that module into ghci
ghc:
src/Data/Generics/Twi...When building syb 0.3.6 with todays head / 7.5
I get different type error messages for the module Data/Generics/Twins.hs
respectively from ghc when doing cabal install syb vs when i load that module into ghci
ghc:
src/Data/Generics/Twins.hs:202:14:
Illegal polymorphic or qualified type: GenericT
Perhaps you intended to use -XRankNTypes or -XRank2Types
In the type signature for `gzipWithT':
gzipWithT :: GenericQ (GenericT) -> GenericQ (GenericT)
src/Data/Generics/Twins.hs:213:14:
Illegal polymorphic or qualified type: GenericM m
Perhaps you intended to use -XRankNTypes or -XRank2Types
In the type signature for `gzipWithM':
<table><tr><th>gzipWithM </th>
<td>Monad m =\></td></tr>
<tr><td></td>
<td>GenericQ (GenericM m) -\> GenericQ (GenericM m)</td></tr></table>
src/Data/Generics/Twins.hs:223:14:
Illegal polymorphic or qualified type: GenericQ r
Perhaps you intended to use -XRankNTypes or -XRank2Types
In the type signature for `gzipWithQ':
gzipWithQ :: GenericQ (GenericQ r) -> GenericQ (GenericQ [r])
src/Data/Generics/Twins.hs:265:9:
Illegal polymorphic or qualified type: GenericM Maybe
Perhaps you intended to use -XRankNTypes or -XRank2Types
In the type signature for `gzip':
> gzip :: GenericQ (GenericM Maybe) -\> GenericQ (GenericM Maybe)
--- interestingly, rank2types is infact enabled in that module.
whereas when the module is loaded into ghci, I get a very different error message
Loading package base ... linking ... done.
\[1 of 2\] Compiling Data.Generics.Aliases ( Data/Generics/Aliases.hs, interpreted )
\[2 of 2\] Compiling Data.Generics.Twins ( Data/Generics/Twins.hs, interpreted )
Data/Generics/Twins.hs:118:12: Not in scope: type variable `b'
Data/Generics/Twins.hs:118:17: Not in scope: type variable `a'
Data/Generics/Twins.hs:118:39: Not in scope: type variable `b'
Data/Generics/Twins.hs:118:42: Not in scope: type variable `a'
----
irrespective of fixing the type error (i hope to sort that out this evening),
the type error message should be the same between ghc and ghci in this instance right?
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.5 |
| 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":"inconsistent type error messages between ghc and ghci","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.5","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"When building syb 0.3.6 with todays head / 7.5\r\nI get different type error messages for the module Data/Generics/Twins.hs\r\nrespectively from ghc when doing cabal install syb vs when i load that module into ghci\r\n\r\nghc:\r\n\r\nsrc/Data/Generics/Twins.hs:202:14:\r\n Illegal polymorphic or qualified type: GenericT\r\n Perhaps you intended to use -XRankNTypes or -XRank2Types\r\n In the type signature for `gzipWithT':\r\n gzipWithT :: GenericQ (GenericT) -> GenericQ (GenericT)\r\n\r\nsrc/Data/Generics/Twins.hs:213:14:\r\n Illegal polymorphic or qualified type: GenericM m\r\n Perhaps you intended to use -XRankNTypes or -XRank2Types\r\n In the type signature for `gzipWithM':\r\n gzipWithM :: Monad m =>\r\n GenericQ (GenericM m) -> GenericQ (GenericM m)\r\n\r\nsrc/Data/Generics/Twins.hs:223:14:\r\n Illegal polymorphic or qualified type: GenericQ r\r\n Perhaps you intended to use -XRankNTypes or -XRank2Types\r\n In the type signature for `gzipWithQ':\r\n gzipWithQ :: GenericQ (GenericQ r) -> GenericQ (GenericQ [r])\r\n\r\nsrc/Data/Generics/Twins.hs:265:9:\r\n Illegal polymorphic or qualified type: GenericM Maybe\r\n Perhaps you intended to use -XRankNTypes or -XRank2Types\r\n In the type signature for `gzip':\r\n gzip :: GenericQ (GenericM Maybe) -> GenericQ (GenericM Maybe)\r\n\r\n\r\n--- interestingly, rank2types is infact enabled in that module.\r\n\r\nwhereas when the module is loaded into ghci, I get a very different error message\r\n\r\nLoading package base ... linking ... done.\r\n[1 of 2] Compiling Data.Generics.Aliases ( Data/Generics/Aliases.hs, interpreted )\r\n[2 of 2] Compiling Data.Generics.Twins ( Data/Generics/Twins.hs, interpreted )\r\n\r\nData/Generics/Twins.hs:118:12: Not in scope: type variable `b'\r\n\r\nData/Generics/Twins.hs:118:17: Not in scope: type variable `a'\r\n\r\nData/Generics/Twins.hs:118:39: Not in scope: type variable `b'\r\n\r\nData/Generics/Twins.hs:118:42: Not in scope: type variable `a'\r\n\r\n\r\n---- \r\nirrespective of fixing the type error (i hope to sort that out this evening),\r\nthe type error message should be the same between ghc and ghci in this instance right?","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/6026Unboxed operators have wrong fixity2019-07-07T18:52:31ZbenlUnboxed operators have wrong fixity```
$ ghci -XMagicHash
$ :m GHC.Exts
> 1 + 2 * 3
7
> I# (1# +# 2# *# 3#)
9
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version |...```
$ ghci -XMagicHash
$ :m GHC.Exts
> 1 + 2 * 3
7
> I# (1# +# 2# *# 3#)
9
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| 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":"Unboxed operators have wrong fixity","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{\r\n$ ghci -XMagicHash\r\n$ :m GHC.Exts\r\n> 1 + 2 * 3\r\n7\r\n> I# (1# +# 2# *# 3#)\r\n9\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.8.1Ian Lynagh <igloo@earth.li>Ian Lynagh <igloo@earth.li>https://gitlab.haskell.org/ghc/ghc/-/issues/6012No warning for Incorrect display of 15! (factorial 15) when type is Int -> Int2019-07-07T18:52:35ZGeorge.AtelierNo warning for Incorrect display of 15! (factorial 15) when type is Int -> IntGHCi version: 7.0.4
Offending function:
factorial :: Int -\> Int
factorial 0 = 1
factorial n = n \* factorial (n-1)
Correct answer is displayed (as expected) when type is
factorial :: Integer -\> Integer
THE BUG IS THE DISPLAY OF A ...GHCi version: 7.0.4
Offending function:
factorial :: Int -\> Int
factorial 0 = 1
factorial n = n \* factorial (n-1)
Correct answer is displayed (as expected) when type is
factorial :: Integer -\> Integer
THE BUG IS THE DISPLAY OF A CORRECT-LOOKING INCORRECT ANSWER THAT RESULTED FROM (UNREPORTED) OVERFLOW OF Int (but not of Integer)
\~\~ Thank you
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.0.4 |
| 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":"No warning for Incorrect display of 15! (factorial 15) when type is Int -> Int","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.4","keywords":["Int","Integer","recursion"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"GHCi version: 7.0.4\r\n\r\nOffending function:\r\n\r\nfactorial :: Int -> Int\r\nfactorial 0 = 1\r\nfactorial n = n * factorial (n-1)\r\n\r\n\r\nCorrect answer is displayed (as expected) when type is\r\n\r\nfactorial :: Integer -> Integer\r\n\r\nTHE BUG IS THE DISPLAY OF A CORRECT-LOOKING INCORRECT ANSWER THAT RESULTED FROM (UNREPORTED) OVERFLOW OF Int (but not of Integer)\r\n\r\n~~ Thank you\r\n\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/5966getAppUserDataDirectory does not respect XDG specification2019-07-07T18:52:49ZordcodergetAppUserDataDirectory does not respect XDG specificationgetAppUserDataDirectory function from System.Directory module returns path to a dot-dir under home directory. This swamps home with many hidden directories, when there are many applications installed. There is [XDG specification](http://...getAppUserDataDirectory function from System.Directory module returns path to a dot-dir under home directory. This swamps home with many hidden directories, when there are many applications installed. There is [XDG specification](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html) for this situation, which suggests using $XDG_DATA_HOME environment variable.
So, getAppUserDataDirectory should behave approximately like this when $XDG_DATA_HOME is set:
```
getAppUserDataDirectory appName = do
path <- getEnv "XDG_DATA_HOME"
return (path++'/':appName)
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------- |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/directory |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"getAppUserDataDirectory does not respect XDG specification","status":"New","operating_system":"","component":"libraries/directory","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"getAppUserDataDirectory function from System.Directory module returns path to a dot-dir under home directory. This swamps home with many hidden directories, when there are many applications installed. There is [http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG specification] for this situation, which suggests using $XDG_DATA_HOME environment variable.\r\n\r\nSo, getAppUserDataDirectory should behave approximately like this when $XDG_DATA_HOME is set:\r\n{{{\r\ngetAppUserDataDirectory appName = do\r\n path <- getEnv \"XDG_DATA_HOME\"\r\n return (path++'/':appName)\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Edward KmettEdward Kmetthttps://gitlab.haskell.org/ghc/ghc/-/issues/5962Data.Typeable: types which should compare equal don't2019-07-07T18:52:50ZGhost UserData.Typeable: types which should compare equal don'tHere are two ways to construct a TypeRep for the type () -\> ():
```
Prelude> import Data.Typeable
Prelude Data.Typeable> let unitToUnit = typeOf (\() -> ())
Prelude Data.Typeable> let unitToUnit' = mkFunTy (typeOf ()) (typeOf ())
```
...Here are two ways to construct a TypeRep for the type () -\> ():
```
Prelude> import Data.Typeable
Prelude Data.Typeable> let unitToUnit = typeOf (\() -> ())
Prelude Data.Typeable> let unitToUnit' = mkFunTy (typeOf ()) (typeOf ())
```
It seems to work:
```
Prelude Data.Typeable> unitToUnit
() -> ()
Prelude Data.Typeable> unitToUnit'
() -> ()
```
But the two TypeReps are not equal:
```
Prelude Data.Typeable> unitToUnit == unitToUnit'
False
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| 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":"Data.Typeable: types which should compare equal don't","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Here are two ways to construct a TypeRep for the type () -> ():\r\n\r\n{{{\r\nPrelude> import Data.Typeable\r\nPrelude Data.Typeable> let unitToUnit = typeOf (\\() -> ())\r\nPrelude Data.Typeable> let unitToUnit' = mkFunTy (typeOf ()) (typeOf ())\r\n}}}\r\n\r\nIt seems to work:\r\n\r\n{{{\r\nPrelude Data.Typeable> unitToUnit\r\n() -> ()\r\nPrelude Data.Typeable> unitToUnit'\r\n() -> ()\r\n}}}\r\n\r\nBut the two TypeReps are not equal:\r\n\r\n{{{\r\nPrelude Data.Typeable> unitToUnit == unitToUnit'\r\nFalse\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.4.3Simon Peyton JonesSimon Peyton Joneshttps://gitlab.haskell.org/ghc/ghc/-/issues/5940Unicode characters in the command line get messed up2019-07-07T18:52:55Zvolker-wyskUnicode characters in the command line get messed upThe command line isn't properly decoded to Unicode. The following program demonstrates the bug:
import System
main = do
> \[a\] \<- getArgs
> putStrLn (show a)
When called like this:
1. /bug ä
The program will output this:
> "\\...The command line isn't properly decoded to Unicode. The following program demonstrates the bug:
import System
main = do
> \[a\] \<- getArgs
> putStrLn (show a)
When called like this:
1. /bug ä
The program will output this:
> "\\195\\164"
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.0.4 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Unicode characters in the command line get messed up","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.4","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The command line isn't properly decoded to Unicode. The following program demonstrates the bug:\r\n\r\nimport System\r\nmain = do\r\n [a] <- getArgs\r\n putStrLn (show a)\r\n\r\nWhen called like this:\r\n\r\n ./bug ä\r\n\r\nThe program will output this:\r\n\r\n \"\\195\\164\"\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/5915Code using seq has wrong strictness when unoptimised (too strict)2019-07-07T18:53:01Zmichal.palkaCode using seq has wrong strictness when unoptimised (too strict)The following piece of code gets miscompiled if no optimisation is used. The program crashes instead of printing `[0]`, which would be the correct behaviour. GHC 7.3.20111127 has been used for triggering this bug.
```
test = seq (seq id...The following piece of code gets miscompiled if no optimisation is used. The program crashes instead of printing `[0]`, which would be the correct behaviour. GHC 7.3.20111127 has been used for triggering this bug.
```
test = seq (seq id (\a -> undefined a))
main = do
print $ test [0]
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------------- |
| Version | 7.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | michal.palka@poczta.fm |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Code using seq has wrong strictness when unoptimised (too strict)","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.3","keywords":["lazy","seq","strict","strictness"],"differentials":[],"test_case":"","architecture":"","cc":["michal.palka@poczta.fm"],"type":"Bug","description":"The following piece of code gets miscompiled if no optimisation is used. The program crashes instead of printing `[0]`, which would be the correct behaviour. GHC 7.3.20111127 has been used for triggering this bug.\r\n\r\n{{{\r\ntest = seq (seq id (\\a -> undefined a))\r\n\r\nmain = do\r\n print $ test [0]\r\n}}}\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/5885+RTS -? does not work2019-07-07T18:53:08Ztakano-akio+RTS -? does not workCompile the following hello.hs:
main = putStrLn "hello"
with:
ghc -rtsopts hello.hs
Then run it:
1. /hello +RTS -?
I get "hello", but a help message is expected.
<details><summary>Trac metadata</summary>
| Trac field ...Compile the following hello.hs:
main = putStrLn "hello"
with:
ghc -rtsopts hello.hs
Then run it:
1. /hello +RTS -?
I get "hello", but a help message is expected.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"+RTS -? does not work","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Compile the following hello.hs:\r\n\r\nmain = putStrLn \"hello\"\r\n\r\nwith:\r\n\r\nghc -rtsopts hello.hs\r\n\r\nThen run it:\r\n\r\n./hello +RTS -?\r\n\r\nI get \"hello\", but a help message is expected.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/5870writeChan is not 100% exception-safe2019-07-07T18:53:11ZjoeyadamswriteChan is not 100% exception-safeControl.Concurrent.Chan.writeChan is currently implemented like this:
```
writeChan :: Chan a -> a -> IO ()
writeChan (Chan _ writeVar) val = do
new_hole <- newEmptyMVar
modifyMVar_ writeVar $ \old_hole -> do
putMVar old_hole (C...Control.Concurrent.Chan.writeChan is currently implemented like this:
```
writeChan :: Chan a -> a -> IO ()
writeChan (Chan _ writeVar) val = do
new_hole <- newEmptyMVar
modifyMVar_ writeVar $ \old_hole -> do
putMVar old_hole (ChItem val new_hole)
return new_hole
```
The problem is that modifyMVar_ restores the exception mask when it calls the callback. If an asynchronous exception is delivered immediately after the putMVar, the Chan's write end will be set to a filled hole, violating a key invariant.
I think it should be implemented like this:
```
writeChan :: Chan a -> a -> IO ()
writeChan (Chan _ writeVar) val = do
new_hole <- newEmptyMVar
mask_ $ do
old_hole <- takeMVar writeVar -- (1)
putMVar old_hole (ChItem val new_hole) -- (2)
putMVar writeVar new_hole -- (3)
```
This looks a bit naïve, but it should be atomic, at least in theory:
- (1) is interruptible. However, if it is interrupted, the MVar will remain intact.
- (2) is not interruptible, because old_hole is guaranteed to be empty. No other thread can fill it because we have taken exclusive access to writeVar.
- (3) is not interruptible, because we have taken exclusive access to writeVar.
This implementation has the added benefit of removing an exception handler, which should make it slightly faster.
readChan is okay, though:
```
readChan :: Chan a -> IO a
readChan (Chan readVar _) = do
modifyMVar readVar $ \read_end -> do
(ChItem val new_read_end) <- readMVar read_end
return (new_read_end, val)
```
If an exception is received immediately after the readMVar, then the read cursor will not be advanced, and the next call to readChan will simply read from that position again. Unfortunately, we can't get rid of the exception handler like we did with writeChan, because `readMVar read_end` is interruptible.
The attached patch changes the implementation of writeChan to the one shown above, and adds a comment to the definition of Chan about the write end's empty-hole invariant. I believe all of the Chan operations preserve this invariant, even the deprecated unGetChan and isEmptyChan.
I have not been able to create a test case where writeChan is interrupted between filling the hole and updating the write cursor. Perhaps it doesn't actually happen in practice, or perhaps it is extremely rare. But by my understanding of the semantics:
```
mask $ \restore -> do
thing1
restore $ putMVar ...
thing2
```
It is possible for an exception to arrive after the putMVar and before thing2.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| 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":"writeChan is not 100% exception-safe","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Control.Concurrent.Chan.writeChan is currently implemented like this:\r\n\r\n{{{\r\nwriteChan :: Chan a -> a -> IO ()\r\nwriteChan (Chan _ writeVar) val = do\r\n new_hole <- newEmptyMVar\r\n modifyMVar_ writeVar $ \\old_hole -> do\r\n putMVar old_hole (ChItem val new_hole)\r\n return new_hole\r\n}}}\r\n\r\nThe problem is that modifyMVar_ restores the exception mask when it calls the callback. If an asynchronous exception is delivered immediately after the putMVar, the Chan's write end will be set to a filled hole, violating a key invariant.\r\n\r\nI think it should be implemented like this:\r\n\r\n{{{\r\nwriteChan :: Chan a -> a -> IO ()\r\nwriteChan (Chan _ writeVar) val = do\r\n new_hole <- newEmptyMVar\r\n mask_ $ do\r\n old_hole <- takeMVar writeVar -- (1)\r\n putMVar old_hole (ChItem val new_hole) -- (2)\r\n putMVar writeVar new_hole -- (3)\r\n}}}\r\n\r\nThis looks a bit naïve, but it should be atomic, at least in theory:\r\n\r\n * (1) is interruptible. However, if it is interrupted, the MVar will remain intact.\r\n\r\n * (2) is not interruptible, because old_hole is guaranteed to be empty. No other thread can fill it because we have taken exclusive access to writeVar.\r\n\r\n * (3) is not interruptible, because we have taken exclusive access to writeVar.\r\n\r\nThis implementation has the added benefit of removing an exception handler, which should make it slightly faster.\r\n\r\nreadChan is okay, though:\r\n\r\n{{{\r\nreadChan :: Chan a -> IO a\r\nreadChan (Chan readVar _) = do\r\n modifyMVar readVar $ \\read_end -> do\r\n (ChItem val new_read_end) <- readMVar read_end\r\n return (new_read_end, val)\r\n}}}\r\n\r\nIf an exception is received immediately after the readMVar, then the read cursor will not be advanced, and the next call to readChan will simply read from that position again. Unfortunately, we can't get rid of the exception handler like we did with writeChan, because {{{readMVar read_end}}} is interruptible.\r\n\r\nThe attached patch changes the implementation of writeChan to the one shown above, and adds a comment to the definition of Chan about the write end's empty-hole invariant. I believe all of the Chan operations preserve this invariant, even the deprecated unGetChan and isEmptyChan.\r\n\r\nI have not been able to create a test case where writeChan is interrupted between filling the hole and updating the write cursor. Perhaps it doesn't actually happen in practice, or perhaps it is extremely rare. But by my understanding of the semantics:\r\n\r\n{{{\r\nmask $ \\restore -> do\r\n thing1\r\n restore $ putMVar ...\r\n thing2\r\n}}}\r\n\r\nIt is possible for an exception to arrive after the putMVar and before thing2.","type_of_failure":"OtherFailure","blocking":[]} -->7.4.2Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/5865threadDelay is disrupted by system clock changes2019-07-07T18:53:13ZjoeyadamsthreadDelay is disrupted by system clock changesthreadDelay is sensitive to changes to the system clock. Two behaviors are observed:
- When the system clock is moved forward, threadDelay will timeout prematurely, because it thinks that amount of time elapsed.
- When the system clock ...threadDelay is sensitive to changes to the system clock. Two behaviors are observed:
- When the system clock is moved forward, threadDelay will timeout prematurely, because it thinks that amount of time elapsed.
- When the system clock is moved backward, threadDelay will take longer to complete, because it's waiting for the system clock to catch up.
Whether these behaviors are present depends on both the operating system and the use of -threaded. Here are the configurations I tested:
- ghc-7.4.1 Linux 64-bit: Disrupted by both forward and backward clock changes
- ghc-7.4.1 Linux 64-bit, **-threaded**: Disrupted only by backward clock changes
- ghc-7.2.2 Windows 32-bit: Not disrupted by clock changes (behaves correctly)
- ghc-7.2.2 Windows 32-bit, **-threaded**: Disrupted only by backward clock changes
To reproduce the problem, first compile the attached program. It uses System.Posix.Clock from the "clock" package to get the time, unaffected by system clock changes. Then run it. It will produce output like this:
```
0: 0s
1: 10s
```
Set the system clock forward by a minute. On Linux without -threaded, it will print something like this:
```
5: 50s
6: 52s
```
6 is printed 2 seconds after 5, because threadDelay didn't wait a full 10 seconds like it should have.
Now set the system clock backward by a minute. On Windows with -threaded, or on Linux with or without -threaded, it will print something like this:
```
3: 30s
4: 101s
```
4 is printed over a minute after 3, because threadDelay waited for the system clock to recover the time subtracted by changing the time.
For convenience, here's a way to fix the system clock on Linux after fiddling around with it:
```
sudo ntpdate pool.ntp.org
```
Digging through the source, each configuration seems to boil down to the following system calls:
- Linux: gettimeofday (via getourtimeofday in posix/Itimer.c)
- Linux, **-threaded**: gettimeofday, epoll_wait
- Windows: [Sleep](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298%28v=vs.85%29.aspx)
- Windows, **-threaded**: [GetSystemTimeAsFileTime](http://msdn.microsoft.com/en-us/library/windows/desktop/ms724397%28v=vs.85%29.aspx), [WaitForSingleObject](http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx)
Perhaps the calls to gettimeofday and GetSystemTimeAsFileTime should be replaced with monotonic time functions (i.e. ones not affected by system clock changes):
- Linux, FreeBSD: http://stackoverflow.com/q/211055/149391
- Mac OS X: http://stackoverflow.com/a/6725161/149391
- Windows: http://stackoverflow.com/q/211257/149391
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"threadDelay is disrupted by system clock changes","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"threadDelay is sensitive to changes to the system clock. Two behaviors are observed:\r\n\r\n * When the system clock is moved forward, threadDelay will timeout prematurely, because it thinks that amount of time elapsed.\r\n\r\n * When the system clock is moved backward, threadDelay will take longer to complete, because it's waiting for the system clock to catch up.\r\n\r\nWhether these behaviors are present depends on both the operating system and the use of -threaded. Here are the configurations I tested:\r\n\r\n * ghc-7.4.1 Linux 64-bit: Disrupted by both forward and backward clock changes\r\n\r\n * ghc-7.4.1 Linux 64-bit, '''-threaded''': Disrupted only by backward clock changes\r\n\r\n * ghc-7.2.2 Windows 32-bit: Not disrupted by clock changes (behaves correctly)\r\n\r\n * ghc-7.2.2 Windows 32-bit, '''-threaded''': Disrupted only by backward clock changes\r\n\r\nTo reproduce the problem, first compile the attached program. It uses System.Posix.Clock from the \"clock\" package to get the time, unaffected by system clock changes. Then run it. It will produce output like this:\r\n\r\n{{{\r\n0: 0s\r\n1: 10s\r\n}}}\r\n\r\nSet the system clock forward by a minute. On Linux without -threaded, it will print something like this:\r\n\r\n{{{\r\n5: 50s\r\n6: 52s\r\n}}}\r\n\r\n6 is printed 2 seconds after 5, because threadDelay didn't wait a full 10 seconds like it should have.\r\n\r\nNow set the system clock backward by a minute. On Windows with -threaded, or on Linux with or without -threaded, it will print something like this:\r\n\r\n{{{\r\n3: 30s\r\n4: 101s\r\n}}}\r\n\r\n4 is printed over a minute after 3, because threadDelay waited for the system clock to recover the time subtracted by changing the time.\r\n\r\nFor convenience, here's a way to fix the system clock on Linux after fiddling around with it:\r\n\r\n{{{\r\nsudo ntpdate pool.ntp.org\r\n}}}\r\n\r\nDigging through the source, each configuration seems to boil down to the following system calls:\r\n\r\n * Linux: gettimeofday (via getourtimeofday in posix/Itimer.c)\r\n\r\n * Linux, '''-threaded''': gettimeofday, epoll_wait\r\n\r\n * Windows: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298%28v=vs.85%29.aspx Sleep]\r\n\r\n * Windows, '''-threaded''': [http://msdn.microsoft.com/en-us/library/windows/desktop/ms724397%28v=vs.85%29.aspx GetSystemTimeAsFileTime], [http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx WaitForSingleObject]\r\n\r\nPerhaps the calls to gettimeofday and GetSystemTimeAsFileTime should be replaced with monotonic time functions (i.e. ones not affected by system clock changes):\r\n\r\n * Linux, FreeBSD: http://stackoverflow.com/q/211055/149391\r\n\r\n * Mac OS X: http://stackoverflow.com/a/6725161/149391\r\n\r\n * Windows: http://stackoverflow.com/q/211257/149391","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1pcapriottipcapriottihttps://gitlab.haskell.org/ghc/ghc/-/issues/5859unsafeInterleaveIO duplicates computation when evaluated by multiple threads2024-01-16T02:53:33ZjoeyadamsunsafeInterleaveIO duplicates computation when evaluated by multiple threadsWhen the following code is compiled with -O1 or -O2, the interleaved computation (putStrLn "eval") is performed 1000 times, rather than once:
```
import Control.Concurrent
import Control.Exception (evaluate)
import Control.Monad
import ...When the following code is compiled with -O1 or -O2, the interleaved computation (putStrLn "eval") is performed 1000 times, rather than once:
```
import Control.Concurrent
import Control.Exception (evaluate)
import Control.Monad
import System.IO.Unsafe
main :: IO ()
main = do
x <- unsafeInterleaveIO $ putStrLn "eval"
replicateM_ 1000 $ forkIO $ evaluate x >> return ()
threadDelay 1000000
```
Taking a look at the source to unsafeInterleaveIO:
```
{-# INLINE unsafeInterleaveIO #-}
unsafeInterleaveIO :: IO a -> IO a
unsafeInterleaveIO m = unsafeDupableInterleaveIO (noDuplicate >> m)
-- We believe that INLINE on unsafeInterleaveIO is safe, because the
-- state from this IO thread is passed explicitly to the interleaved
-- IO, so it cannot be floated out and shared.
```
It seems the comment about INLINE is not true. If I define the following function:
```
interleave :: IO a -> IO a
interleave = unsafeInterleaveIO
{-# NOINLINE interleave #-}
```
and replace unsafeInterleaveIO with interleave, "eval" is printed only once. If I change NOINLINE to INLINE, or if I remove the pragma altogether, "eval" is printed 1000 times.
I believe unsafeInterleaveIO should *guarantee* that computations are not repeated. Otherwise, we end up with strangeness like this:
```
import Control.Applicative
import Control.Concurrent
import Control.Monad
main :: IO ()
main = do
chan <- newChan :: IO (Chan Int)
mapM_ (writeChan chan) [0..999]
items <- take 10 <$> getChanContents chan
replicateM_ 5 $ forkIO $ putStrLn $ "items = " ++ show items
threadDelay 1000000
```
which prints:
```
items = [0,1,2,3,4,5,6,7,8,9]
items = [10,11,12,13,14,15,16,17,18,19]
items = [20,21,22,23,24,25,26,27,28,29]
items = [30,31,32,33,34,35,36,37,38,39]
items = [40,41,42,43,44,45,46,47,48,49]
```
For the time being, programs can work around this by using a NOINLINE wrapper:
```
getChanContents' :: Chan a -> IO [a]
getChanContents' = getChanContents
{-# NOINLINE getChanContents' #-}
```
I tested this on Linux 64-bit with GHC 7.2.2 and ghc-7.4.0.20120111, and on Windows 32-bit with GHC 7.0.3 and 7.2.2. All of these platforms and versions exhibit the same behavior. The bug goes away when the program is compiled with -O0, or when functions returning interleaved computations are marked NOINLINE (e.g. getChanContents').
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.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":"unsafeInterleaveIO duplicates computation when evaluated by multiple threads","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"When the following code is compiled with -O1 or -O2, the interleaved computation (putStrLn \"eval\") is performed 1000 times, rather than once:\r\n\r\n{{{\r\nimport Control.Concurrent\r\nimport Control.Exception (evaluate)\r\nimport Control.Monad\r\nimport System.IO.Unsafe\r\n\r\nmain :: IO ()\r\nmain = do\r\n x <- unsafeInterleaveIO $ putStrLn \"eval\"\r\n replicateM_ 1000 $ forkIO $ evaluate x >> return ()\r\n threadDelay 1000000\r\n}}}\r\n\r\nTaking a look at the source to unsafeInterleaveIO:\r\n\r\n{{{\r\n{-# INLINE unsafeInterleaveIO #-}\r\nunsafeInterleaveIO :: IO a -> IO a\r\nunsafeInterleaveIO m = unsafeDupableInterleaveIO (noDuplicate >> m)\r\n\r\n-- We believe that INLINE on unsafeInterleaveIO is safe, because the\r\n-- state from this IO thread is passed explicitly to the interleaved\r\n-- IO, so it cannot be floated out and shared.\r\n}}}\r\n\r\nIt seems the comment about INLINE is not true. If I define the following function:\r\n\r\n{{{\r\ninterleave :: IO a -> IO a\r\ninterleave = unsafeInterleaveIO\r\n{-# NOINLINE interleave #-}\r\n}}}\r\n\r\nand replace unsafeInterleaveIO with interleave, \"eval\" is printed only once. If I change NOINLINE to INLINE, or if I remove the pragma altogether, \"eval\" is printed 1000 times.\r\n\r\nI believe unsafeInterleaveIO should ''guarantee'' that computations are not repeated. Otherwise, we end up with strangeness like this:\r\n\r\n{{{\r\nimport Control.Applicative\r\nimport Control.Concurrent\r\nimport Control.Monad\r\n\r\nmain :: IO ()\r\nmain = do\r\n chan <- newChan :: IO (Chan Int)\r\n mapM_ (writeChan chan) [0..999]\r\n items <- take 10 <$> getChanContents chan\r\n replicateM_ 5 $ forkIO $ putStrLn $ \"items = \" ++ show items\r\n threadDelay 1000000\r\n}}}\r\n\r\nwhich prints:\r\n\r\n{{{\r\nitems = [0,1,2,3,4,5,6,7,8,9]\r\nitems = [10,11,12,13,14,15,16,17,18,19]\r\nitems = [20,21,22,23,24,25,26,27,28,29]\r\nitems = [30,31,32,33,34,35,36,37,38,39]\r\nitems = [40,41,42,43,44,45,46,47,48,49]\r\n}}}\r\n\r\nFor the time being, programs can work around this by using a NOINLINE wrapper:\r\n\r\n{{{\r\ngetChanContents' :: Chan a -> IO [a]\r\ngetChanContents' = getChanContents\r\n{-# NOINLINE getChanContents' #-}\r\n}}}\r\n\r\nI tested this on Linux 64-bit with GHC 7.2.2 and ghc-7.4.0.20120111, and on Windows 32-bit with GHC 7.0.3 and 7.2.2. All of these platforms and versions exhibit the same behavior. The bug goes away when the program is compiled with -O0, or when functions returning interleaved computations are marked NOINLINE (e.g. getChanContents').","type_of_failure":"OtherFailure","blocking":[]} -->Simon Peyton JonesSimon Peyton Jones