GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2024-03-17T18:32:24Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/8695Arithmetic overflow from (minBound :: Int) `quot` (-1)2024-03-17T18:32:24ZrleslieArithmetic overflow from (minBound :: Int) `quot` (-1)According to the documentation for Data.Int, “All arithmetic is performed modulo 2!\^n, where n is the number of bits in the type.”
However, this promise is broken by the following exception:
```
Prelude> (minBound :: Int) `quot` (-1)
...According to the documentation for Data.Int, “All arithmetic is performed modulo 2!\^n, where n is the number of bits in the type.”
However, this promise is broken by the following exception:
```
Prelude> (minBound :: Int) `quot` (-1)
*** Exception: arithmetic overflow
```
(This also occurs with Int8, Int16, Int32, and Int64, and likewise for `div`.)
If all arithmetic is performed modulo 2!\^n, I would rather expect the above to evaluate to `minBound`, since after all `minBound * (-1) == minBound`. The fact that an exception is raised adds an unnecessary burden in pure code to ensure `quot` (or `div`) is never called with these specific arguments.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------------ |
| Version | 7.6.3 |
| Type | Bug |
| TypeOfFailure | IncorrectResultAtRuntime |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/haskell2010 |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Arithmetic overflow from (minBound :: Int) `quot` (-1)","status":"New","operating_system":"","component":"libraries/haskell2010","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"According to the documentation for Data.Int, “All arithmetic is performed modulo 2!^n, where n is the number of bits in the type.”\r\n\r\nHowever, this promise is broken by the following exception:\r\n\r\n{{{\r\nPrelude> (minBound :: Int) `quot` (-1)\r\n*** Exception: arithmetic overflow\r\n}}}\r\n\r\n(This also occurs with Int8, Int16, Int32, and Int64, and likewise for `div`.)\r\n\r\nIf all arithmetic is performed modulo 2!^n, I would rather expect the above to evaluate to `minBound`, since after all `minBound * (-1) == minBound`. The fact that an exception is raised adds an unnecessary burden in pure code to ensure `quot` (or `div`) is never called with these specific arguments.","type_of_failure":"IncorrectResultAtRuntime","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/8362Filesystem related tests failed on solaris (SmartOS)2019-07-07T18:45:23ZlerouxFilesystem related tests failed on solaris (SmartOS)Getting filesystem (files/permissions) related test faiures on SmartOS (32bit).
```
$ uname -a
SunOS pkgx86 5.11 joyent_20130919T215407Z i86pc i386 i86pc Solaris
```
Unexpected failures: `TEST="openFile003 getPermissions001 processGrou...Getting filesystem (files/permissions) related test faiures on SmartOS (32bit).
```
$ uname -a
SunOS pkgx86 5.11 joyent_20130919T215407Z i86pc i386 i86pc Solaris
```
Unexpected failures: `TEST="openFile003 getPermissions001 processGroup002 user001 posix005"`
The testsuite output is attached.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 7.6.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | libraries (other) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Filesystem related tests failed on solaris (SmartOS)","status":"New","operating_system":"","component":"libraries (other)","related":[],"milestone":"7.8.3","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Getting filesystem (files/permissions) related test faiures on SmartOS (32bit).\r\n\r\n{{{\r\n$ uname -a\r\nSunOS pkgx86 5.11 joyent_20130919T215407Z i86pc i386 i86pc Solaris\r\n}}}\r\n\r\nUnexpected failures: `TEST=\"openFile003 getPermissions001 processGroup002 user001 posix005\"`\r\n\r\nThe testsuite output is attached.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/8285unexpected behavior with encodeFloat on large inputs2019-07-07T18:45:43ZCarter Schonwaldunexpected behavior with encodeFloat on large inputs```
> encodeFloat 1 1023
8.98846567431158e307 -- ok
> encodeFloat 1 1024
Infinity -- ok
> encodeFloat 1 (2^31 - 1)
Infinity -- ok
> encodeFloat 1 (2^31)
0.0 -- not ok
``````
> encodeFloat 1 1023
8.98846567431158e307 -- ok
> encodeFloat 1 1024
Infinity -- ok
> encodeFloat 1 (2^31 - 1)
Infinity -- ok
> encodeFloat 1 (2^31)
0.0 -- not ok
```8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7997waitForProcess and getProcessExitCode are unsafe against asynchronous except...2019-07-07T18:47:07ZdfrankewaitForProcess and getProcessExitCode are unsafe against asynchronous exceptionsIn this description of the current behavior of *waitForProcess*, assume for simplicity the following:
1. The process being waited on has already terminated.
1. Neither *waitForProcess* nor *getProcessExitCode* has previously been called...In this description of the current behavior of *waitForProcess*, assume for simplicity the following:
1. The process being waited on has already terminated.
1. Neither *waitForProcess* nor *getProcessExitCode* has previously been called for this *ProcessHandle*.
1. *waitpid()* returns success on the first try; it does not get interrupted by a signal.
Under these assumptions, *waitForProcess* currently behaves as follows:
1. It is passed a *ProcessHandle* named *ph*. *ProcessHandle* is defined like so:
```
data ProcessHandle__ = OpenHandle PHANDLE | ClosedHandle ExitCode
newtype ProcessHandle = ProcessHandle (MVar ProcessHandle__)
```
1. It allocate a *CInt* using *alloca*; the pointer to it is named *pret*.
1. It passes *pret* to *c_waitForProcess*. *c_waitForProcess* makes a system call to *waitpid()*, and populates *pret* with the result.
1. *waitForProcess* peeks into *pret* and then mutates *ph*, changing it from an *OpenHandle* to a *ClosedHandle*.
There is already a comment in the source code mentioning that this approach is unsafe:
```
-- don't hold the MVar while we call c_waitForProcess...
-- (XXX but there's a small race window here during which another
-- thread could close the handle or call waitForProcess)
```
, which is correct. However, it is also unsafe against asynchronous exceptions, and would remain so even if the *MVar* were held during the *c_waitForProcess* call. If an asynchronous exception occurs in between steps 3 and 4, then the system will be left in a state in which the child process has been successfully waited on by the OS, but the *ProcessHandle* is still in an *OpenHandle* state and the exit code has been lost. A subsequent call to *waitForProcess* will result in *waitpid()* unexpectedly returning ECHILD, or worse, the OS will have recycled the child process's PID and *waitpid()* will wait on the wrong process.
*getProcessExitCode* has the same bug.
I propose fixing this by redefining *ProcessHandle* like so:
```
data ProcessHandle = ProcessHandle PHANDLE (Ptr CInt) (MVar (Ptr CInt))
```
, where the second argument maybe points to the process's return code, and the third argument contains a pointer to a boolean flag indicating whether the second argument points to something meaningful. Extend the signature of *c_waitForProcess* to take both pointers. Then, let *c_waitForProcess* provide the following contract. If called as *c_waitForProcess ph pret pflag*:
1. *\*pflag* is required to be false at the start of the call.
1. If and only if the call to *waitpid()* returns successfully, then *\*pflag* will be set to true and *\*pret* will be populated with the exit code.
Then, *waitForProcess* can behave as follows:
1. The entire routine is wrapped in *withMVar*. Asynchronous exceptions are allowed to occur.
1. If *\*pflag* is true, then construct an *ExitCode* from *\*pret* and return it.
1. Otherwise, call *c_waitForProcess* (with the same retry behavior as presently), and then construct and return an *ExitCode* after a successful return.
And *getProcessExitCode* can:
1. Mask exceptions.
1. *tryTakeMVar*. If the *MVar* is already held, unmask exceptions and return *Nothing*.
1. Peek at *\*pflag*.
1. Replace the *MVar*.
1. Unmask exceptions.
1. If *\*pflag* is true, then construct and return an *ExitCode* from *\*pret*.
1. Otherwise, return *Nothing*.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 7.6.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/process |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"waitForProcess and getProcessExitCode are unsafe against asynchronous exceptions","status":"New","operating_system":"","component":"libraries/process","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"In this description of the current behavior of ''waitForProcess'', assume for simplicity the following:\r\n\r\n1. The process being waited on has already terminated.\r\n\r\n2. Neither ''waitForProcess'' nor ''getProcessExitCode'' has previously been called for this ''ProcessHandle''.\r\n\r\n3. ''waitpid()'' returns success on the first try; it does not get interrupted by a signal.\r\n\r\nUnder these assumptions, ''waitForProcess'' currently behaves as follows:\r\n\r\n1. It is passed a ''ProcessHandle'' named ''ph''. ''ProcessHandle'' is defined like so:\r\n\r\n{{{\r\ndata ProcessHandle__ = OpenHandle PHANDLE | ClosedHandle ExitCode\r\nnewtype ProcessHandle = ProcessHandle (MVar ProcessHandle__)\r\n}}}\r\n\r\n2. It allocate a ''CInt'' using ''alloca''; the pointer to it is named ''pret''. \r\n\r\n3. It passes ''pret'' to ''c_waitForProcess''. ''c_waitForProcess'' makes a system call to ''waitpid()'', and populates ''pret'' with the result.\r\n\r\n4. ''waitForProcess'' peeks into ''pret'' and then mutates ''ph'', changing it from an ''OpenHandle'' to a ''ClosedHandle''.\r\n\r\nThere is already a comment in the source code mentioning that this approach is unsafe:\r\n\r\n\r\n{{{\r\n -- don't hold the MVar while we call c_waitForProcess...\r\n -- (XXX but there's a small race window here during which another\r\n -- thread could close the handle or call waitForProcess)\r\n}}}\r\n\r\n, which is correct. However, it is also unsafe against asynchronous exceptions, and would remain so even if the ''MVar'' were held during the ''c_waitForProcess'' call. If an asynchronous exception occurs in between steps 3 and 4, then the system will be left in a state in which the child process has been successfully waited on by the OS, but the ''ProcessHandle'' is still in an ''OpenHandle'' state and the exit code has been lost. A subsequent call to ''waitForProcess'' will result in ''waitpid()'' unexpectedly returning ECHILD, or worse, the OS will have recycled the child process's PID and ''waitpid()'' will wait on the wrong process.\r\n\r\n''getProcessExitCode'' has the same bug.\r\n\r\nI propose fixing this by redefining ''ProcessHandle'' like so:\r\n\r\n{{{\r\ndata ProcessHandle = ProcessHandle PHANDLE (Ptr CInt) (MVar (Ptr CInt))\r\n}}}\r\n\r\n, where the second argument maybe points to the process's return code, and the third argument contains a pointer to a boolean flag indicating whether the second argument points to something meaningful. Extend the signature of ''c_waitForProcess'' to take both pointers. Then, let ''c_waitForProcess'' provide the following contract. If called as ''c_waitForProcess ph pret pflag'':\r\n\r\n1. ''*pflag'' is required to be false at the start of the call.\r\n\r\n2. If and only if the call to ''waitpid()'' returns successfully, then ''*pflag'' will be set to true and ''*pret'' will be populated with the exit code.\r\n\r\nThen, ''waitForProcess'' can behave as follows:\r\n\r\n1. The entire routine is wrapped in ''withMVar''. Asynchronous exceptions are allowed to occur.\r\n\r\n2. If ''*pflag'' is true, then construct an ''ExitCode'' from ''*pret'' and return it.\r\n\r\n3. Otherwise, call ''c_waitForProcess'' (with the same retry behavior as presently), and then construct and return an ''ExitCode'' after a successful return.\r\n\r\nAnd ''getProcessExitCode'' can:\r\n\r\n1. Mask exceptions.\r\n\r\n2. ''tryTakeMVar''. If the ''MVar'' is already held, unmask exceptions and return ''Nothing''.\r\n\r\n3. Peek at ''*pflag''.\r\n\r\n4. Replace the ''MVar''.\r\n\r\n5. Unmask exceptions.\r\n\r\n6. If ''*pflag'' is true, then construct and return an ''ExitCode'' from ''*pret''.\r\n\r\n7. Otherwise, return ''Nothing''.","type_of_failure":"OtherFailure","blocking":[]} -->Michael Snoymanmichael@snoyman.comMichael Snoymanmichael@snoyman.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/7398RULES don't apply to a newtype constructor2020-01-23T19:38:31ZshachafRULES don't apply to a newtype constructorFor some reason, RULES that involve a newtype constructor never seem to fire. The following program demonstrates the problem:
```
module Main where
newtype Foo a = Foo { unFoo :: a }
deriving Show
foo :: a -> Foo a
foo = Foo
{-# RU...For some reason, RULES that involve a newtype constructor never seem to fire. The following program demonstrates the problem:
```
module Main where
newtype Foo a = Foo { unFoo :: a }
deriving Show
foo :: a -> Foo a
foo = Foo
{-# RULES "rule Foo" forall v. Foo v = error "Foo" #-}
{-# RULES "rule foo" forall v. foo v = error "foo" #-}
main :: IO ()
main = do
print (Foo ())
print (foo ())
```
"rule foo" fires, but "rule Foo" doesn't. The program prints
```
Foo {unFoo = ()}
D: foo
```
Note that this doesn't seem to affect selectors, only constructors.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------------ |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | IncorrectResultAtRuntime |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"RULES don't apply to a newtype constructor","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"For some reason, RULES that involve a newtype constructor never seem to fire. The following program demonstrates the problem:\r\n\r\n{{{\r\nmodule Main where\r\n\r\nnewtype Foo a = Foo { unFoo :: a }\r\n deriving Show\r\n\r\nfoo :: a -> Foo a\r\nfoo = Foo\r\n\r\n{-# RULES \"rule Foo\" forall v. Foo v = error \"Foo\" #-}\r\n{-# RULES \"rule foo\" forall v. foo v = error \"foo\" #-}\r\n\r\nmain :: IO ()\r\nmain = do\r\n print (Foo ())\r\n print (foo ())\r\n}}}\r\n\r\n\"rule foo\" fires, but \"rule Foo\" doesn't. The program prints\r\n\r\n{{{\r\nFoo {unFoo = ()}\r\nD: foo\r\n}}}\r\n\r\nNote that this doesn't seem to affect selectors, only constructors.","type_of_failure":"IncorrectResultAtRuntime","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/7297LLVM incorrectly hoisting loads2019-07-07T18:50:28ZdtereiLLVM incorrectly hoisting loadstest 367_letnoescape fails under LLVM as a load of the !HpLim register is hoisted out of the loop. So yielding is never done.
What I am not sure about right now is the best way to fix. Loads in LLVM can be annotated in a few different w...test 367_letnoescape fails under LLVM as a load of the !HpLim register is hoisted out of the loop. So yielding is never done.
What I am not sure about right now is the best way to fix. Loads in LLVM can be annotated in a few different ways to fix this and not sure which one is the most 'correct'.
All the following work:
- mark the load as volatile. (seems to give nicest code as well)
- mark the load as atomic with either monotonic or seq_cst ordering.
- mark the load as both volatile and atomic.
This bug while only affecting a single test case seems very serious and potentially indicative of a large problem. How well are we communicating the load/store threaded semantics to LLVM?
And what semantics do we need to communicate? I think we are fine other than the STG registers...
So making a bug for now as I don't know yet the best way to proceed without dedicating some time to reading LLVM docs and probably talking to the LLVM devs as the docs on the memory model are fairly confusing.
e.g., Code in question:
Bad version (LBB0_1 loops forever as load hoisted out):
```
r1Uf_info: # @r1Uf_info
# BB#0: # %c1Vy
movq 144(%r13), %rax
decq %r14
.align 16, 0x90
.LBB0_1: # %tailrecurse
# =>This Inner Loop Header: Depth=1
incq %r14
testq %rax, %rax
jne .LBB0_1
# BB#2: # %c1VD
movq -8(%r13), %rax
movl $r1Uf_closure, %ebx
jmpq *%rax # TAILCALL
```
Code when marked with atomic (either monatonic or seq_cst) or both atomic and volatile:
```
r1Uf_info: # @r1Uf_info
# BB#0: # %c1Vy
decq %r14
.align 16, 0x90
.LBB0_1: # %tailrecurse
# =>This Inner Loop Header: Depth=1
incq %r14
movq 144(%r13), %rax
testq %rax, %rax
jne .LBB0_1
# BB#2: # %c1VD
movq -8(%r13), %rax
movl $r1Uf_closure, %ebx
jmpq *%rax # TAILCALL
```
Code when marked volatile:
```
r1Uf_info: # @r1Uf_info
# BB#0: # %c1Vy
decq %r14
.align 16, 0x90
.LBB0_1: # %tailrecurse
# =>This Inner Loop Header: Depth=1
incq %r14
cmpq $0, 144(%r13)
jne .LBB0_1
# BB#2: # %c1VD
movq -8(%r13), %rax
movl $r1Uf_closure, %ebx
jmpq *%rax # TAILCALL
```8.0.1dtereidtereihttps://gitlab.haskell.org/ghc/ghc/-/issues/7246Callstack depends on way (prof, profasm, profthreaded2019-07-07T18:50:42ZJoachim Breitnermail@joachim-breitner.deCallstack depends on way (prof, profasm, profthreadedConsider the attached test case. The expected output is the that of the ```prof``` way, while for ```profasm``` and ```profthreaded```, I get this result:
```
=====> callstack003(profthreaded) 19 of 21 [0, 1, 0]
cd . && '/home/jojo/doku...Consider the attached test case. The expected output is the that of the ```prof``` way, while for ```profasm``` and ```profthreaded```, I get this result:
```
=====> callstack003(profthreaded) 19 of 21 [0, 1, 0]
cd . && '/home/jojo/dokumente/Uni/info/ghc/inplace/bin/ghc-stage2' -fforce-recomp -dcore-lint -dcmm-lint -dno-debug-output -no-user-package-db -rtsopts -fno-ghci-history -o callstack003 callstack003.hs -O -prof -auto-all -threaded -fprof-auto-calls -fno-full-laziness -fno-state-hack >callstack003.comp.stderr 2>&1
cd . && ./callstack003 +RTS -p -RTS </dev/null >callstack003.run.stdout 2>callstack003.run.stderr
Actual stdout output differs from expected:
--- ./callstack003.stdout 2012-09-17 11:27:02.607458948 +0200
+++ ./callstack003.run.stdout 2012-09-17 12:20:33.988109494 +0200
@@ -1,8 +1,8 @@
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
*** unexpected failure for callstack003(profthreaded)
```
Not sure if this really hurts anyone, and the behavior of the call stack WRT recursive calls is anyways not quite perfect yet (see #7240), this makes adding good test cases a bit difficult.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Profiling |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Callstack depends on way (prof, profasm, profthreaded","status":"New","operating_system":"","component":"Profiling","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Consider the attached test case. The expected output is the that of the ```prof``` way, while for ```profasm``` and ```profthreaded```, I get this result:\r\n\r\n{{{\r\n=====> callstack003(profthreaded) 19 of 21 [0, 1, 0]\r\ncd . && '/home/jojo/dokumente/Uni/info/ghc/inplace/bin/ghc-stage2' -fforce-recomp -dcore-lint -dcmm-lint -dno-debug-output -no-user-package-db -rtsopts -fno-ghci-history -o callstack003 callstack003.hs -O -prof -auto-all -threaded -fprof-auto-calls -fno-full-laziness -fno-state-hack >callstack003.comp.stderr 2>&1\r\ncd . && ./callstack003 +RTS -p -RTS </dev/null >callstack003.run.stdout 2>callstack003.run.stderr\r\nActual stdout output differs from expected:\r\n--- ./callstack003.stdout\t2012-09-17 11:27:02.607458948 +0200\r\n+++ ./callstack003.run.stdout\t2012-09-17 12:20:33.988109494 +0200\r\n@@ -1,8 +1,8 @@\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n*** unexpected failure for callstack003(profthreaded)\r\n}}}\r\n\r\nNot sure if this really hurts anyone, and the behavior of the call stack WRT recursive calls is anyways not quite perfect yet (see #7240), this makes adding good test cases a bit difficult.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/5611Asynchronous exception discarded after safe FFI call2019-07-07T18:54:23ZjoeyadamsAsynchronous exception discarded after safe FFI call**Note:** This bug appears to be fixed already, as it does not appear with GHC 7.2.1 . I'm submitting a bug report anyway, to document its presence.
The bug is: when an asynchronous exception is thrown to a thread making a (safe) foreig...**Note:** This bug appears to be fixed already, as it does not appear with GHC 7.2.1 . I'm submitting a bug report anyway, to document its presence.
The bug is: when an asynchronous exception is thrown to a thread making a (safe) foreign call, the thread throwing the exception blocks like it should, but then the exception isn't actually delivered. For example:
```haskell
{-# LANGUAGE ForeignFunctionInterface #-}
import Control.Concurrent
import Foreign.C
import System.IO
foreign import ccall safe "unistd.h sleep"
sleep :: CUInt -> IO CUInt
main :: IO ()
main = do
hSetBuffering stdout LineBuffering
tid <- forkIO $ do
putStrLn "child: Sleeping"
_ <- sleep 1
-- The following lines should not happen after the killThread from the
-- parent thread completes. However, they do...
putStrLn "child: Done sleeping"
threadDelay 1000000
putStrLn "child: Done waiting"
threadDelay 100000
putStrLn $ "parent: Throwing exception to thread " ++ show tid
throwTo tid $ userError "Exception delivered successfully"
putStrLn "parent: Done throwing exception"
threadDelay 2000000
```
When the bug is present, the program prints:
```
child: Sleeping
parent: Throwing exception to thread ThreadId 4
child: Done sleeping
parent: Done throwing exception
child: Done waiting
```
"child: Done waiting" should not be printed after completion of the throwTo, and the exception message should appear. On GHC 7.2.1, the program prints:
```
child: Sleeping
parent: Throwing exception to thread ThreadId 4
parent: Done throwing exception
ffi-sleep: user error (Exception delivered successfully)
```
This bug has been reproduced in GHC 7.0.3, on both Linux and Windows. It has also been reproduced on GHC 7.0.4.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.0.3 |
| 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":"Asynchronous exception discarded after safe FFI call","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.3","keywords":["FFI,","exception"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"'''Note:''' This bug appears to be fixed already, as it does not appear with GHC 7.2.1 . I'm submitting a bug report anyway, to document its presence.\r\n\r\nThe bug is: when an asynchronous exception is thrown to a thread making a (safe) foreign call, the thread throwing the exception blocks like it should, but then the exception isn't actually delivered. For example:\r\n\r\n{{{\r\n\r\n{-# LANGUAGE ForeignFunctionInterface #-}\r\n\r\nimport Control.Concurrent\r\nimport Foreign.C\r\nimport System.IO\r\n\r\nforeign import ccall safe \"unistd.h sleep\"\r\n sleep :: CUInt -> IO CUInt\r\n\r\nmain :: IO ()\r\nmain = do\r\n hSetBuffering stdout LineBuffering\r\n\r\n tid <- forkIO $ do\r\n putStrLn \"child: Sleeping\"\r\n _ <- sleep 1\r\n\r\n -- The following lines should not happen after the killThread from the\r\n -- parent thread completes. However, they do...\r\n putStrLn \"child: Done sleeping\"\r\n threadDelay 1000000\r\n putStrLn \"child: Done waiting\"\r\n\r\n threadDelay 100000\r\n putStrLn $ \"parent: Throwing exception to thread \" ++ show tid\r\n throwTo tid $ userError \"Exception delivered successfully\"\r\n putStrLn \"parent: Done throwing exception\"\r\n\r\n threadDelay 2000000\r\n}}}\r\n\r\nWhen the bug is present, the program prints:\r\n\r\n{{{\r\nchild: Sleeping\r\nparent: Throwing exception to thread ThreadId 4\r\nchild: Done sleeping\r\nparent: Done throwing exception\r\nchild: Done waiting\r\n}}}\r\n\r\n\"child: Done waiting\" should not be printed after completion of the throwTo, and the exception message should appear. On GHC 7.2.1, the program prints:\r\n\r\n{{{\r\nchild: Sleeping\r\nparent: Throwing exception to thread ThreadId 4\r\nparent: Done throwing exception\r\nffi-sleep: user error (Exception delivered successfully)\r\n}}}\r\n\r\nThis bug has been reproduced in GHC 7.0.3, on both Linux and Windows. It has also been reproduced on GHC 7.0.4.","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/3998strace breaks System.Process(?)2019-07-07T19:01:12Zgreenrdstrace breaks System.Process(?)See http://markmail.org/message/hbf5pf5puvxnxmxo\#query:strace%20greenrd%20ghc+page:1+mid:nfzfholb5gbrsyqm+state:results
Still an issue in 6.12.1.
<details><summary>Trac metadata</summary>
| Trac field | Value |
|...See http://markmail.org/message/hbf5pf5puvxnxmxo\#query:strace%20greenrd%20ghc+page:1+mid:nfzfholb5gbrsyqm+state:results
Still an issue in 6.12.1.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 6.12.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | x86 |
</details>
<!-- {"blocked_by":[],"summary":"strace breaks System.Process(?)","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.12.1","keywords":[],"differentials":[],"test_case":"","architecture":"x86","cc":[""],"type":"Bug","description":"See http://markmail.org/message/hbf5pf5puvxnxmxo#query:strace%20greenrd%20ghc+page:1+mid:nfzfholb5gbrsyqm+state:results\r\n\r\nStill an issue in 6.12.1.","type_of_failure":"OtherFailure","blocking":[]} -->Michael Snoymanmichael@snoyman.comMichael Snoymanmichael@snoyman.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/24345Concurrent GHC sessions clobber RTS linker state2024-02-02T17:24:01ZAlexis KingConcurrent GHC sessions clobber RTS linker stateThe following example program (derived from `T3372`) illustrates how concurrent GHC sessions can clobber each other’s RTS linker state:
```haskell
{-# LANGUAGE MagicHash #-}
module Main where
import Data.Foldable
import System.Environm...The following example program (derived from `T3372`) illustrates how concurrent GHC sessions can clobber each other’s RTS linker state:
```haskell
{-# LANGUAGE MagicHash #-}
module Main where
import Data.Foldable
import System.Environment
import GHC (Ghc)
import qualified GHC
import qualified GHC.Driver.Monad as GHC
import qualified GHC.Driver.Session as GHC
import qualified GHC.Platform.Ways as GHC
import qualified GHC.Exts
main :: IO ()
main = do
let test1 = "M1.hs"
let test2 = "M2.hs"
writeFile test1 "module M where x = 1"
writeFile test2 "module M where x = 2"
ghc_1 <- newGhcSession
ghc_2 <- newGhcSession
line "1" $ runInSession ghc_1 $ load (test1, "M")
line "2" $ runInSession ghc_2 $ load (test2, "M")
line "3" $ runInSession ghc_1 $ eval "x"
line "4" $ runInSession ghc_2 $ eval "x"
line "5" $ runInSession ghc_1 $ eval "x"
where
line n a = putStr (n ++ ": ") >> a
type ModuleName = String
newGhcSession :: IO GHC.Session
newGhcSession = do
(libdir:_) <- getArgs
session <- GHC.runGhc (Just libdir) (GHC.reifyGhc pure)
runInSession session $ do
df <- GHC.getSessionDynFlags
let platform = GHC.targetPlatform df
GHC.setSessionDynFlags $
foldl' (flip GHC.setGeneralFlag')
df{GHC.ghcMode = GHC.CompManager,
GHC.ghcLink = GHC.LinkInMemory,
GHC.targetWays_ = GHC.hostFullWays,
GHC.verbosity = 0}
(concatMap (GHC.wayGeneralFlags platform) GHC.hostFullWays)
pure session
runInSession :: GHC.Session -> Ghc a -> IO a
runInSession = flip GHC.reflectGhc
load :: (FilePath, ModuleName) -> Ghc ()
load (f, mn) = do
target <- GHC.guessTarget f Nothing Nothing
GHC.setTargets [target]
res <- GHC.load GHC.LoadAllTargets
GHC.liftIO $ putStrLn ("Load " ++ showSuccessFlag res)
GHC.setContext
[ GHC.IIDecl $ GHC.simpleImportDecl $ GHC.mkModuleName "Prelude"
, GHC.IIDecl $ GHC.simpleImportDecl $ GHC.mkModuleName mn ]
where
showSuccessFlag GHC.Succeeded = "succeeded"
showSuccessFlag GHC.Failed = "failed"
eval :: String -> Ghc ()
eval e = do
show_e <- GHC.compileExpr $ "(show ("++ e ++")) :: String"
GHC.liftIO $ putStrLn (GHC.Exts.unsafeCoerce# show_e)
```
Compiling and running this program yields the following output:
```haskell
$ ghc -dynamic -package ghc Main
[1 of 2] Compiling Main ( Main.hs, Main.o )
[2 of 2] Linking Main [Objects changed]
$ ./Main "$(ghc --print-libdir)"
1: Load succeeded
2: Load succeeded
3: 1
4: 2
5: 2
```
The final line of output is the bug; it should print `1`, but instead it prints `2`.
## Explanation
The above program creates two concurrent GHC sessions and loads a module into each one. The modules share the same name and export the same symbol, but the symbol has a different value in each module.
Since the backend is the NCG and the program is dynamically-linked, each GHC session compiles the loaded module to a `.o` file, then links the `.o` file into a `.so` file on demand. The first time the two sessions each evaluate a reference to the loaded symbol, the results are `1` and `2`, respectively, which is correct. However, when the symbol is evaluated in the first session a second time, the `2` value from the second session is printed, instead. In effect, the module loaded in the second session has overwritten the module loaded in the first session, which is quite surprising.
This symbol clobbering only affects symbols loaded from shared objects, and it only affects the symbols resolved from an interpreted context. Even if symbols are “overwritten” in this way, references from native code will still refer to the original, correct symbols. However, any references in newly-created bytecode will be incorrect, and references from existing bytecode objects will become incorrect if the bytecode objects are relinked. Note also that the clobbering is truly on a symbol-by-symbol basis: if the second module were to export some, but not all, of the first module’s symbols, the values of those symbols would be selectively clobbered, leaving the first session in an inconsistent state. If the replaced symbols’ types differ from their replacements, memory corruption or segfaults are likely to occur.
## Cause
Currently, the state of the RTS linker is process-global. This includes the RTS symbol table, the list of loaded code objects, and the list of loaded shared libraries. GHC generally expects that it is the exclusive client of the RTS linker, and this assumption is essentially always correct, but concurrent GHC sessions break this assumption, which can result in various misbehaviors.
When the RTS linker is used to load static `.o` files or `.a` archives, it does all the work of loading the objects itself, including maintaining its own symbol table. For this reason, if the above example is compiled without the `-dynamic` option, the outcome is quite different:
```
$ ghc -package ghc Main
[1 of 2] Compiling Main ( Main.hs, Main.o )
[2 of 2] Linking Main [Objects changed]
$ ./Main "$(ghc --print-libdir)"
1: Load succeeded
2: Load succeeded
3: 1
GHC runtime linker: fatal error: I found a duplicate definition for symbol
M_x_closure
whilst processing object file
/tmp/haskell/M2.o
The symbol was previously defined in
/tmp/haskell/M1.o
This could be caused by:
* Loading two different object files which export the same symbol
* Specifying the same object file twice on the GHCi command line
* An incorrect `package.conf' entry, causing some object to be
loaded twice.
4: Main: loadObj "/tmp/haskell/M2.o": failed
```
Since the RTS maintains its own symbol table in this configuration, it can detect the symbol collision and report the error. This behavior is arguably still wrong—there is no fundamental reason that the two sessions must share a symbol table, and other session state is kept separate—but it’s at least less mysterious.
In contrast, when the RTS loads a shared library, it defers the work to the system dynamic linker (via `dlopen` on Linux and macOS). System dynamic linkers do not provide APIs to obtain the full list of symbols provided by a shared library, so the RTS cannot possibly determine whether two libraries provide conflicting symbols. When a symbol is looked up, each library is tried in order until the symbol is found, starting from the library that was most recently loaded. Within a single interpreter session, this strategy provides the generally-desirable property that new symbols shadow old ones (since most symbol conflicts arise from loading a new version of the same code), but it is much less defensible if multiple sessions exist in the same process.https://gitlab.haskell.org/ghc/ghc/-/issues/13584ghci parse error on operator info2021-01-20T10:16:18Zakegaljghci parse error on operator infoIf requested info about some operator, ie `(+)` `:info (+)` is working as expected:
```haskell
> :i (+)
class Num a where
(+) :: a -> a -> a
...
-- Defined in ‘GHC.Num’
infixl 6 +
```
When additional space character is there `:i...If requested info about some operator, ie `(+)` `:info (+)` is working as expected:
```haskell
> :i (+)
class Num a where
(+) :: a -> a -> a
...
-- Defined in ‘GHC.Num’
infixl 6 +
```
When additional space character is there `:info (+ )` it won't parse:
```haskell
> :i (+ )
<interactive>:1:3: error:
parse error (possibly incorrect indentation or mismatched brackets)
```
Note that the same thing is working with `:type` so its strange it doesn't use the same parser in both places:
```haskell
> :t (+ )
(+ ) :: Num a => a -> a -> a
```https://gitlab.haskell.org/ghc/ghc/-/issues/9307LLVM vs NCG: floating point numbers close to zero have different sign2019-07-07T18:40:56Zjrp2014LLVM vs NCG: floating point numbers close to zero have different signCompiling HEAD with perf-llvm, (3.4.2) and running the nofib suite fails at the wave4main case. It is not clear to me whether wave4main should always produce the same output (and so the test fails because it does not do so) or whether th...Compiling HEAD with perf-llvm, (3.4.2) and running the nofib suite fails at the wave4main case. It is not clear to me whether wave4main should always produce the same output (and so the test fails because it does not do so) or whether the numbers generated depend on some feature of the build settings, or OS.
```
HC = /Users/xxx/Projects/ghc/inplace/bin/ghc-stage2
HC_OPTS = -O2 -Rghc-timing -H32m -hisuf hi -cpp -fglasgow-exts -rtsopts
RUNTEST_OPTS = -ghc-timing
==nofib== wave4main: size of wave4main follows...
__TEXT __DATA __OBJC others dec hex
4091904 450560 0 4295947176 4300489640 1005443a8
==nofib== wave4main: time to run wave4main follows...
../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000;
real 0m0.217s
user 0m0.191s
sys 0m0.011s
././wave4main 4000 < /dev/null
expected stdout not matched by reality
--- wave4main.stdout 2014-07-08 20:57:14.000000000 +0100
+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest16932.1 2014-07-13 13:43:22.000000000 +0100
@@ -1 +1 @@
-69923/1465
+69096/1465
real 0m0.197s
user 0m0.186s
sys 0m0.008s
././wave4main 4000 < /dev/null
expected stdout not matched by reality
--- wave4main.stdout 2014-07-08 20:57:14.000000000 +0100
+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest16961.1 2014-07-13 13:43:22.000000000 +0100
@@ -1 +1 @@
-69923/1465
+69096/1465
real 0m0.201s
user 0m0.189s
sys 0m0.009s
././wave4main 4000 < /dev/null
expected stdout not matched by reality
--- wave4main.stdout 2014-07-08 20:57:14.000000000 +0100
+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest17011.1 2014-07-13 13:43:22.000000000 +0100
@@ -1 +1 @@
-69923/1465
+69096/1465
real 0m0.201s
user 0m0.190s
sys 0m0.008s
././wave4main 4000 < /dev/null
expected stdout not matched by reality
--- wave4main.stdout 2014-07-08 20:57:14.000000000 +0100
+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest17051.1 2014-07-13 13:43:23.000000000 +0100
@@ -1 +1 @@
-69923/1465
+69096/1465
real 0m0.200s
user 0m0.189s
sys 0m0.009s
././wave4main 4000 < /dev/null
expected stdout not matched by reality
--- wave4main.stdout 2014-07-08 20:57:14.000000000 +0100
+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest17080.1 2014-07-13 13:43:23.000000000 +0100
@@ -1 +1 @@
-69923/1465
+69096/1465
make: *** [runtests] Error 1
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | --------------------- |
| Version | 7.8.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | NoFib benchmark suite |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"wave4main in nofib fails","status":"New","operating_system":"","component":"NoFib benchmark suite","related":[],"milestone":"7.10.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.8.3","keywords":["wave4main"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"\r\nCompiling HEAD with perf-llvm, (3.4.2) and running the nofib suite fails at the wave4main case. It is not clear to me whether wave4main should always produce the same output (and so the test fails because it does not do so) or whether the numbers generated depend on some feature of the build settings, or OS.\r\n\r\n\r\n{{{\r\nHC = /Users/xxx/Projects/ghc/inplace/bin/ghc-stage2\r\nHC_OPTS = -O2 -Rghc-timing -H32m -hisuf hi -cpp -fglasgow-exts -rtsopts\r\nRUNTEST_OPTS = -ghc-timing\r\n==nofib== wave4main: size of wave4main follows...\r\n__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\r\n4091904\t450560\t0\t4295947176\t4300489640\t1005443a8\r\n==nofib== wave4main: time to run wave4main follows...\r\n../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000; ../../../runstdtest/runstdtest ./wave4main -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -o1 wave4main.stdout -o1 wave4main.stdout2 -o1 wave4main.stdout3 -ghc-timing 4000;\r\n\r\nreal\t0m0.217s\r\nuser\t0m0.191s\r\nsys\t0m0.011s\r\n././wave4main 4000 < /dev/null\r\nexpected stdout not matched by reality\r\n--- wave4main.stdout\t2014-07-08 20:57:14.000000000 +0100\r\n+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest16932.1\t2014-07-13 13:43:22.000000000 +0100\r\n@@ -1 +1 @@\r\n-69923/1465\r\n+69096/1465\r\n\r\nreal\t0m0.197s\r\nuser\t0m0.186s\r\nsys\t0m0.008s\r\n././wave4main 4000 < /dev/null\r\nexpected stdout not matched by reality\r\n--- wave4main.stdout\t2014-07-08 20:57:14.000000000 +0100\r\n+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest16961.1\t2014-07-13 13:43:22.000000000 +0100\r\n@@ -1 +1 @@\r\n-69923/1465\r\n+69096/1465\r\n\r\nreal\t0m0.201s\r\nuser\t0m0.189s\r\nsys\t0m0.009s\r\n././wave4main 4000 < /dev/null\r\nexpected stdout not matched by reality\r\n--- wave4main.stdout\t2014-07-08 20:57:14.000000000 +0100\r\n+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest17011.1\t2014-07-13 13:43:22.000000000 +0100\r\n@@ -1 +1 @@\r\n-69923/1465\r\n+69096/1465\r\n\r\nreal\t0m0.201s\r\nuser\t0m0.190s\r\nsys\t0m0.008s\r\n././wave4main 4000 < /dev/null\r\nexpected stdout not matched by reality\r\n--- wave4main.stdout\t2014-07-08 20:57:14.000000000 +0100\r\n+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest17051.1\t2014-07-13 13:43:23.000000000 +0100\r\n@@ -1 +1 @@\r\n-69923/1465\r\n+69096/1465\r\n\r\nreal\t0m0.200s\r\nuser\t0m0.189s\r\nsys\t0m0.009s\r\n././wave4main 4000 < /dev/null\r\nexpected stdout not matched by reality\r\n--- wave4main.stdout\t2014-07-08 20:57:14.000000000 +0100\r\n+++ /var/folders/d9/94xh7l810mz3_skcsfh68khh0000gn/T//runtest17080.1\t2014-07-13 13:43:23.000000000 +0100\r\n@@ -1 +1 @@\r\n-69923/1465\r\n+69096/1465\r\nmake: *** [runtests] Error 1\r\n\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/8293user001 spuriously fails if getGroupEntryForID correctly fails2019-07-07T18:45:41ZEdward Z. Yanguser001 spuriously fails if getGroupEntryForID correctly failsIn some cases, a user's current group ID can be a number for a non-existent group. While this usually indicates the system is misconfigured in some way, it can also occur inside chroots or other environments where the information in /etc...In some cases, a user's current group ID can be a number for a non-existent group. While this usually indicates the system is misconfigured in some way, it can also occur inside chroots or other environments where the information in /etc/groups is not to be considered reliable. Unfortunately, the user001 has no way of telling that the failure is proper, and fails the test anyway. We ought to do something more robust.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.7 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | lowest |
| Resolution | Unresolved |
| Component | libraries/unix |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"user001 spuriously fails if getGroupEntryForID correctly fails","status":"New","operating_system":"","component":"libraries/unix","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.7","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"In some cases, a user's current group ID can be a number for a non-existent group. While this usually indicates the system is misconfigured in some way, it can also occur inside chroots or other environments where the information in /etc/groups is not to be considered reliable. Unfortunately, the user001 has no way of telling that the failure is proper, and fails the test anyway. We ought to do something more robust.","type_of_failure":"OtherFailure","blocking":[]} -->Edward KmettEdward Kmetthttps://gitlab.haskell.org/ghc/ghc/-/issues/5262Compiling with -O makes some expressions too lazy and causes space leaks2022-10-24T16:34:06Zmichal.palkaCompiling with -O makes some expressions too lazy and causes space leaksHere are some expressions that are executed in a too lazy way when optimisation is turned on in GHC. GHC is known to make some expressions too lazy when full laziness is turned on (as in #917), and indeed some of these expressions execut...Here are some expressions that are executed in a too lazy way when optimisation is turned on in GHC. GHC is known to make some expressions too lazy when full laziness is turned on (as in #917), and indeed some of these expressions execute correctly when you add -fno-full-laziness. However, some of them are compiled too lazy even if -fno-full-laziness is present.
Here are terms that get compiled too lazy with -O only when full strictness is on:
```
seq (id (\a -> seq a (\b -> (undefined::Int))) (undefined::Bool))
\a -> seq (seq a (\b -> seq b null) (undefined::([] ([] Int)) -> [] Int)) (\b -> ([]::[] Int)) length
\a -> seq (id (\b -> seq b (\c -> seq)) (length a)) ([]::[] Int)
```
Here are terms which are compiled too lazy with -O regardless of full strictness:
```
seq (seq (odd (undefined::Int)) (\a -> (undefined::[] (Int -> Bool))))
foldr (\a -> seq) id ((:) True (undefined::[] Bool))
\a -> foldr (\b -> \c -> seq c (\d -> ([]::[] Int))) (undefined::Bool -> [] Int) a False
\a -> (\b -> map (seq b id) (seq b ([]::[] Int))) (seq a (\b -> (undefined::([] Bool))))
map (seq (seq (seq 0 (undefined::Bool)) (\a -> \b -> (undefined::Bool)) (undefined::Int)))
map (seq (seq (id (\a -> (undefined::Int)) ([]::[] Int)) (\a -> undefined::Bool)))
\a -> (\b -> (:) (seq b 2) (b (undefined::Int) 0)) (seq a (\b -> (undefined::Int -> [] Int)))
```
To discover the differences, just run the terms (whose types are \[Int\] -\> \[Int\]) on some partially or fully-defined small lists.
It is possible to construct programs which exhibit space leaks only when optimisation is turned on using some of these terms (examples attached).
All programs have been tested with a pre-built GHC 7.1.20110606 on linux x86-64.
Is this a bug? Well, full laziness comes with a disclaimer that some expressions will get too lazy, but this happens even when we turn off full laziness, so it might be a legitimate bug.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------------ |
| Version | 7.1 |
| Type | Bug |
| TypeOfFailure | IncorrectResultAtRuntime |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Compiling with -O makes some expressions too lazy and causes space leaks","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.1","keywords":["laziness,","leak","space","strictness,"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Here are some expressions that are executed in a too lazy way when optimisation is turned on in GHC. GHC is known to make some expressions too lazy when full laziness is turned on (as in #917), and indeed some of these expressions execute correctly when you add -fno-full-laziness. However, some of them are compiled too lazy even if -fno-full-laziness is present.\r\n\r\nHere are terms that get compiled too lazy with -O only when full strictness is on:\r\n{{{\r\nseq (id (\\a -> seq a (\\b -> (undefined::Int))) (undefined::Bool))\r\n\\a -> seq (seq a (\\b -> seq b null) (undefined::([] ([] Int)) -> [] Int)) (\\b -> ([]::[] Int)) length\r\n\\a -> seq (id (\\b -> seq b (\\c -> seq)) (length a)) ([]::[] Int)\r\n}}}\r\n\r\nHere are terms which are compiled too lazy with -O regardless of full strictness:\r\n{{{\r\nseq (seq (odd (undefined::Int)) (\\a -> (undefined::[] (Int -> Bool))))\r\nfoldr (\\a -> seq) id ((:) True (undefined::[] Bool))\r\n\\a -> foldr (\\b -> \\c -> seq c (\\d -> ([]::[] Int))) (undefined::Bool -> [] Int) a False\r\n\\a -> (\\b -> map (seq b id) (seq b ([]::[] Int))) (seq a (\\b -> (undefined::([] Bool))))\r\nmap (seq (seq (seq 0 (undefined::Bool)) (\\a -> \\b -> (undefined::Bool)) (undefined::Int)))\r\nmap (seq (seq (id (\\a -> (undefined::Int)) ([]::[] Int)) (\\a -> undefined::Bool)))\r\n\\a -> (\\b -> (:) (seq b 2) (b (undefined::Int) 0)) (seq a (\\b -> (undefined::Int -> [] Int)))\r\n}}}\r\n\r\nTo discover the differences, just run the terms (whose types are [Int] -> [Int]) on some partially or fully-defined small lists.\r\n\r\nIt is possible to construct programs which exhibit space leaks only when optimisation is turned on using some of these terms (examples attached).\r\n\r\nAll programs have been tested with a pre-built GHC 7.1.20110606 on linux x86-64.\r\n\r\nIs this a bug? Well, full laziness comes with a disclaimer that some expressions will get too lazy, but this happens even when we turn off full laziness, so it might be a legitimate bug.","type_of_failure":"IncorrectResultAtRuntime","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/4942GHC.ConsoleHandler does not call back application when Close button is pressed2019-07-07T18:57:41ZAmaticGHC.ConsoleHandler does not call back application when Close button is pressedThe test program below is not called back by GHC.ConsoleHandler when the Close button is pressed during the threadDelay call. A message is written to console_event.log as expected when Ctrl-C or Ctrl-Break is pressed, but not when the Cl...The test program below is not called back by GHC.ConsoleHandler when the Close button is pressed during the threadDelay call. A message is written to console_event.log as expected when Ctrl-C or Ctrl-Break is pressed, but not when the Close button is pressed.
```
import Control.Concurrent (threadDelay)
import GHC.ConsoleHandler
import System.IO
onConsoleEventReceived :: ConsoleEvent -> IO ()
onConsoleEventReceived event = withFile "console_event.log" AppendMode $ \ file -> do
hPutStrLn file $ case event of
ControlC -> "Received Ctrl-C event"
Break -> "Received Ctrl-Break event"
Close -> "Received X button event"
_ -> "Received other console event"
hFlush file
main :: IO ()
main = installHandler (Catch onConsoleEventReceived) >> threadDelay (20*1000000)
```
The host OS is Windows XP SP3.
Please let me know if you need any more info.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 6.12.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHC API |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | lightwing15@hotmail.com |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"GHC.ConsoleHandler does not call back application when Close button is pressed","status":"New","operating_system":"","component":"GHC API","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.12.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["lightwing15@hotmail.com"],"type":"Bug","description":"The test program below is not called back by GHC.ConsoleHandler when the Close button is pressed during the threadDelay call. A message is written to console_event.log as expected when Ctrl-C or Ctrl-Break is pressed, but not when the Close button is pressed.\r\n\r\n{{{\r\nimport Control.Concurrent (threadDelay)\r\nimport GHC.ConsoleHandler\r\nimport System.IO\r\n\r\nonConsoleEventReceived :: ConsoleEvent -> IO ()\r\nonConsoleEventReceived event = withFile \"console_event.log\" AppendMode $ \\ file -> do\r\n hPutStrLn file $ case event of\r\n ControlC -> \"Received Ctrl-C event\"\r\n Break -> \"Received Ctrl-Break event\"\r\n Close -> \"Received X button event\"\r\n _ -> \"Received other console event\"\r\n hFlush file\r\n \r\nmain :: IO ()\r\nmain = installHandler (Catch onConsoleEventReceived) >> threadDelay (20*1000000)\r\n}}}\r\n\r\nThe host OS is Windows XP SP3.\r\n\r\nPlease let me know if you need any more info.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/4413(^^) is not correct for Double and Float2019-07-07T18:59:07Zdaniel.is.fischer(^^) is not correct for Double and FloatConsider
```
Prelude> 2 ^^ (-1024)
0.0
Prelude> 0.5 ^^ 1024
5.562684646268003e-309
```
The cause is
```
x ^^ n = if n >= 0 then x^n else recip (x^(negate n))
```
If we change it to
```
x ^^ n = if n >= 0 then x^n...Consider
```
Prelude> 2 ^^ (-1024)
0.0
Prelude> 0.5 ^^ 1024
5.562684646268003e-309
```
The cause is
```
x ^^ n = if n >= 0 then x^n else recip (x^(negate n))
```
If we change it to
```
x ^^ n = if n >= 0 then x^n else ((recip x)^(negate n))
```
it'll do the right thing for Double and Float, and I don't know of any type where it would produce incorrect results.
Does it need a library proposal or can the change be made without?
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.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":"(^^) is not correct for Double and Float","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.1","keywords":["Double,","Float,","exponentiation"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Consider\r\n{{{\r\nPrelude> 2 ^^ (-1024)\r\n0.0\r\nPrelude> 0.5 ^^ 1024\r\n5.562684646268003e-309\r\n}}}\r\nThe cause is\r\n{{{\r\nx ^^ n = if n >= 0 then x^n else recip (x^(negate n))\r\n}}}\r\nIf we change it to\r\n{{{\r\nx ^^ n = if n >= 0 then x^n else ((recip x)^(negate n))\r\n}}}\r\nit'll do the right thing for Double and Float, and I don't know of any type where it would produce incorrect results.\r\n\r\nDoes it need a library proposal or can the change be made without?","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1tcsavagetcsavagehttps://gitlab.haskell.org/ghc/ghc/-/issues/4049Support for ABI versioning of C libraries2019-07-07T19:00:57ZmpiechotkaSupport for ABI versioning of C librariesCurrently the SO files can be versioned - like in libgtk-x11-2.0.so.0. However GHC provides no support for such versioning which may cause problems if the ABI of library will change.
Also it does not provide any support for ldscripts an...Currently the SO files can be versioned - like in libgtk-x11-2.0.so.0. However GHC provides no support for such versioning which may cause problems if the ABI of library will change.
Also it does not provide any support for ldscripts and fails if it seeks for libz.so and only found is ldscript.
More informations:
http://bugs.gentoo.org/show_bug.cgi?id=290974
http://bugs.gentoo.org/show_bug.cgi?id=311361
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 6.12.2 |
| 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":"Support for ldscripts and ABI versioning","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.12.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Currently the SO files can be versioned - like in libgtk-x11-2.0.so.0. However GHC provides no support for such versioning which may cause problems if the ABI of library will change.\r\n\r\nAlso it does not provide any support for ldscripts and fails if it seeks for libz.so and only found is ldscript.\r\n\r\nMore informations:\r\nhttp://bugs.gentoo.org/show_bug.cgi?id=290974\r\nhttp://bugs.gentoo.org/show_bug.cgi?id=311361","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/2401aborting an STM transaction should throw an exception2019-07-07T19:08:45Zsclvaborting an STM transaction should throw an exceptionThe attached test case will hang at +RTS -N2 and above. As noted in the other ticket I submitted (http://hackage.haskell.org/trac/ghc/ticket/2398), this behavior happens on an Core 2 Quad with 64 bit architecture, and does not take place...The attached test case will hang at +RTS -N2 and above. As noted in the other ticket I submitted (http://hackage.haskell.org/trac/ghc/ticket/2398), this behavior happens on an Core 2 Quad with 64 bit architecture, and does not take place on a PowerPC with 32 bit architecture and no multicore.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 6.8.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Unknown |
| Architecture | Unknown |
</details>
<!-- {"blocked_by":[],"summary":"unsafeIOToSTM hangs with 64 bit multicore.","status":"New","operating_system":"Unknown","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.8.3","keywords":[],"differentials":[],"test_case":"","architecture":"Unknown","cc":[""],"type":"Bug","description":"The attached test case will hang at +RTS -N2 and above. As noted in the other ticket I submitted (http://hackage.haskell.org/trac/ghc/ticket/2398), this behavior happens on an Core 2 Quad with 64 bit architecture, and does not take place on a PowerPC with 32 bit architecture and no multicore.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/24187Thunk is incorrectly updated on async exception in GHCi2023-11-14T15:38:34ZAlexis KingThunk is incorrectly updated on async exception in GHCiThe following program produces different results depending on whether it is compiled or interpreted:
```haskell
import Control.Concurrent
import Control.Exception
import System.IO.Unsafe
main :: IO ()
main = do
let io_thunk = unsafeP...The following program produces different results depending on whether it is compiled or interpreted:
```haskell
import Control.Concurrent
import Control.Exception
import System.IO.Unsafe
main :: IO ()
main = do
let io_thunk = unsafePerformIO $ threadDelay 1000000 *> pure ()
eval_thread <- forkIO (evaluate io_thunk *> pure ())
threadDelay 500000
killThread eval_thread
print io_thunk
```
When compiled, the program prints `()`, but when interpreted, it terminates with an exception:
```
$ ghc A.hs
[1 of 2] Compiling Main ( A.hs, A.o )
[2 of 2] Linking A
$ ./A
()
$ ghc --run A.hs
<interactive>: thread killed
```
It seems like `io_thunk` is somehow being incorrectly overwritten as if the async exception were in fact raised synchronously.https://gitlab.haskell.org/ghc/ghc/-/issues/23069Windows: Inconsistent hReady behavior between POSIX and native IO managers2023-03-07T15:01:07ZRyan ScottWindows: Inconsistent hReady behavior between POSIX and native IO managersWhile debugging a Windows-only issue with the `sbv` library (see https://github.com/LeventErkok/sbv/issues/644), it was discovered that the `hReady` function behaves inconsistently between IO managers on Windows. The following two progra...While debugging a Windows-only issue with the `sbv` library (see https://github.com/LeventErkok/sbv/issues/644), it was discovered that the `hReady` function behaves inconsistently between IO managers on Windows. The following two programs attempt to minimize what goes on when `sbv` communicates with an external process:
```hs
-- Producer.hs
module Main where
import System.IO
main :: IO ()
main = do
s <- getLine
putStrLn $ "Responding to: " ++ s
hFlush stdout
_ <- getLine
pure ()
```
```hs
-- Consumer.hs
module Main (main) where
import Control.Concurrent
import System.Environment
import System.Process
import System.IO
main :: IO ()
main = do
args <- getArgs
pgm <- case args of
[p] -> pure p
_ -> error "Pass the path to the producer executable"
(inp, out, _, _) <- runInteractiveProcess pgm [] Nothing Nothing
hPutStrLn inp "Hello"
hFlush inp
threadDelay 1000000
let collect = reverse <$> go ""
go sofar = do isReady <- hReady out
if isReady
then do c <- hGetChar out
go (c : sofar)
else pure sofar
s <- collect
putStrLn $ "Producer says: " ++ s
```
First, compile these programs with:
```
$ ghc-9.2.7 -fforce-recomp Producer.hs -rtsopts
$ ghc-9.2.7 -fforce-recomp Consumer.hs -rtsopts
```
Next, run the following command, first using the POSIX IO manager:
```
$ ./Consumer.exe ./Producer.exe +RTS --io-manager=posix -RTS
Producer says: Responding to: Hello
```
This is the expected result, and this is what happens on Mac and Linux as well.
Now run the same command, but with the native IO manager:
```
$ ./Consumer.exe ./Producer.exe +RTS --io-manager=native -RTS
Producer says:
```
This time, it simply prints out `Producer says:` without any further output. This seems to indicate that the behavior of `hReady` differs with the IO manager, which is not what I would expect.
I used GHC 9.2.7 above, but I get the same results with 9.4.4 and 9.6.1-alpha3 as well.Ben GamariBen Gamari