[GHC] #11180: A program writing to a read-only stdout should not succeed

#11180: A program writing to a read-only stdout should not succeed -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 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: -------------------------------------+------------------------------------- In the shell, redirection of file descriptors can be read-only (<), write- only (>), or read-write (<>). A program trying to write to stdout, while stdout is redirected read-only, currently exits with exit code 0. {{{ $ cat hello.hs main = print "hello world" $ ghc hello.hs ... $ ./hello 1< /dev/null; echo Exit status: $? Exit status: 0 }}} This should however show some error message, and return some non-zero error message, because the write never succeeds. Note that this example is different from `./hello 1> /dev/null`, which rightfully does succeed. As suggested by this [http://roscidus.com/blog/blog/2013/06/09/choosing-a -python-replacement-for-0install/ blog post]:
"If you’re not sure why this is important, imagine the command is `dump-database > backup` and the filesystem is full."
Supposedly OCaml gets this right. For reference, from my bash man page:
*Redirecting Input*
Redirection of input causes the file whose name results from the expansion of word to be opened for reading on file descriptor n, or the standard input (file descriptor 0) if n is not specified.
The general format for redirecting input is:
[n]
-- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11180 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11180: A program writing to a read-only stdout should not succeed -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 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 bgamari): Indeed this is quite unexpected. I believe the relevant code it is `libraries/base/GHC/IO/FD.hs:writeRawBufferPtrNoBlock`. Judging by the code it ought to be throwing an exception. I'm not yet sure why it is not. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11180#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11180: A program writing to a read-only stdout should not succeed -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 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 rwbarton): It does fail if you add a `hFlush stdout` after the `print`. After `main` finishes, apparently control somehow reaches `hs_exit()`, which calls `flushStdHandles()` which in turn calls the Haskell function `flushStdHandles` defined as {{{ -- try to flush stdout/stderr, but don't worry if we fail -- (these handles might have errors, and we don't want to go into -- an infinite loop). flushStdHandles :: IO () flushStdHandles = do hFlush stdout `catchAny` \_ -> return () hFlush stderr `catchAny` \_ -> return () }}} So, it's apparently intentional. I agree this is poor, though. Maybe we should swallow exceptions when flushing stderr, but not stdout? Or at least have the exception handler cause the program to exit with a different status code (if that's still possible at this point)? For what it's worth gcc does the same thing as ghc currently does (the error status of the `fflush` that happens after `main` finishes is apparently not checked). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11180#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11180: A program writing to a read-only stdout should not succeed -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 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 thomie): Or don't do any automatic flushing of handles on exit. Teach people to always flush/close handles manually, as they have to do already with other handles but stdout/stderr, as noted in commit message 47f3a578a22ed5942ed44ddc81dfd362060e78b4: {{{ Author: simonmar <unknown> Date: Fri Jan 21 16:02:48 2005 +0000 [project @ 2005-01-21 16:02:47 by simonmar] Don't try to run finalizers at program exit. This turned out to be hard if not impossible to do in general, so now we don't attempt it at all. The Main.main wrapper, previously called runIO and now called runMainIO, flushes stdout and stderr before exiting. This should catch most cases where programs rely on Handles being flushed at program exit, but note that now if you simply drop a Handle in your program, there's no guarantee it'll be flushed on exit. If the punters complain enough, I suppose we could implement a global Handle table and flush them all at exit... I'd rather not do this if possible, though. Better to teach people to close their Handles properly. }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11180#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11180: A program writing to a read-only stdout should not succeed -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 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 rwbarton): That seems needlessly spiteful and different from every other language and will cause many more data loss problems. It's traditionally the programmer's responsibility to close handles that they opened, but the handles `stdin`/`stdout`/`stderr` are opened automatically and so it makes sense to close them automatically too, or at least behave as though they are closed (by flushing the buffers). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11180#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11180: A program writing to a read-only stdout should not succeed -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11836 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by thomie): * related: => #11836 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11180#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC