[GHC] #11836: Hello World Bug - silent stdout errors

#11836: Hello World Bug - silent stdout errors -------------------------------------+------------------------------------- Reporter: bit | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- == Background This entertaining talk explains the issue: https://www.irill.org/events /ghm-gnu-hackers-meeting/videos/jim-meyering-goodbye-world-the-perils-of- relying-on-output-streams-in-c == hello.hs {{{#!hs main = putStrLn "Hello world" }}} == Run it {{{ $ runhaskell hello.hs > /dev/full ; echo $? hello.hs: <stdout>: hPutChar: resource exhausted (No space left on device) 1 }}} That looks good! We tried to save the output to a file but the disk was full, so we got an error message, and a process exit code indicating failure. == Run it compiled {{{ $ ghc hello.hs $ ./hello > /dev/full ; echo $? 0 }}} Not good! The error was silently ignored, and additionally the process lied when it reported a successful exit status. Why did it behave differently when compiled? When `runhaskell` is used, the buffering of stdout is `NoBuffering` therefore the putStrLn call fails. But when compiled, stdout is in `LineBuffering` mode and therefore the putStrLn call succeeds. The fix: == hello2.hs {{{#!hs import System.IO main = do putStrLn "Hello world" hClose stdout }}} == Run it compiled {{{ $ ghc hello2.hs $ ./hello2 > /dev/full ; echo $? hello: <stdout>: hClose: resource exhausted (No space left on device) 1 }}} Looks good! But there's a catch: {{{ $ runhaskell hello2.hs ; echo $? Hello world ghc: <stdout>: hFlush: illegal operation (handle is closed) 1 }}} Now our program fails to run correctly with `runhaskell` :( It seems that `runhaskell` is running some hidden code after main finished. It is not clear to me how to write a correct "Hello World" that works both compiled and with `runhaskell`. == Summary One of the greatest things about Haskell is that short, clear and concise programs can also be correct. It is my opinion that the original "hello.hs" should Just Workâ˘. Haskell programmers shouldn't have to know that they need to always close stdout before exiting. Especially since it's not even clear how to do it properly... Thank you! -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11836 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11836: Hello World Bug - silent stdout errors -------------------------------------+------------------------------------- Reporter: bit | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by j.waldmann): So the actual bug report is: behaviour of "main = hClose stdout" under runhaskell differs from behaviour of compiled code. Seems like a documentation bug (if any): I think you cannot close stdout in ghci, and runhaskell is something like ghci. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11836#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11836: Hello World Bug - silent stdout errors -------------------------------------+------------------------------------- Reporter: bit | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Iceland_jack): * cc: Iceland_jack (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11836#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11836: Hello World Bug - silent stdout errors -------------------------------------+------------------------------------- Reporter: bit | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11180 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by thomie): * related: => #11180 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11836#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11836: Hello World Bug - silent stdout errors -------------------------------------+------------------------------------- Reporter: bit | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.0.2 Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11180 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * milestone: => 8.0.2 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11836#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11836: Hello World Bug - silent stdout errors -------------------------------------+------------------------------------- Reporter: bit | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11180 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * milestone: 8.0.2 => 8.2.1 Comment: Bumping to 8.2. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11836#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11836: Hello World Bug - silent stdout errors -------------------------------------+------------------------------------- Reporter: bit | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11180 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by siddhanathan): The first case is interesting. The following should fail as intended: {{{#!hs import System.IO main = do hSetBuffering stdout (BlockBuffering (Just 14)) putStrLn "Hello, World!" }}} {{{ $ ghc hello.hs [1 of 1] Compiling Main ( hello.hs, hello.o ) Linking hello ... $ ./hello > /dev/full ; echo $? hello: <stdout>: commitBuffer: resource exhausted (No space left on device) 1 }}} But one small change can make it silently succeed: {{{#!hs import System.IO main = do hSetBuffering stdout (BlockBuffering (Just 15)) putStrLn "Hello, World!" }}} {{{ $ ghc hello.hs [1 of 1] Compiling Main ( hello.hs, hello.o ) Linking hello ... $ ./hello > /dev/full ; echo $? 0 }}} In the absence of an explicit statement for setting the buffering mode, the code might be similar to this: {{{#!hs import System.IO main = do hSetBuffering stdout (BlockBuffering Nothing) putStrLn "Hello, World!" }}} in which case, GHC may resort to using a fairly large number like `dEFAULT_CHAR_BUFFER_SIZE`. To verify that this is the case, you could try the following: {{{#!hs main = putStrLn $ replicate (1024*8) '.' }}} and now things are consistent again: {{{ $ ghc hello.hs [1 of 1] Compiling Main ( hello.hs, hello.o ) Linking hello ... $ ./hello > /dev/full ; echo $? hello: <stdout>: commitBuffer: resource exhausted (No space left on device) 1 }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11836#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC