#4391: forkIO threads do not properly save/restore the floating point 
environment
---------------------------------+------------------------------------------
    Reporter:  draconx           |        Owner:              
        Type:  bug               |       Status:  new         
    Priority:  normal            |    Milestone:  7.2.1       
   Component:  Runtime System    |      Version:  6.12.3      
    Keywords:                    |     Testcase:              
   Blockedby:                    |   Difficulty:              
          Os:  Unknown/Multiple  |     Blocking:              
Architecture:  x86_64 (amd64)    |      Failure:  None/Unknown
---------------------------------+------------------------------------------

Comment(by draconx):

 Replying to [comment:6 rwbarton]:
 > Perhaps a better question is whether it affects "ordinary" programs,
 where by
 > "ordinary" programs I mean ones that don't invoke the `fe*` family of
 > functions (via the FFI) or the equivalent.  My understanding is that it
 does
 > not, but I am not an expert on the subject; please correct me if I am
 wrong.

 Since I don't know _exactly_ what parts of the CPU's floating point state
 are
 not preserved on context switches, it's hard to say what _won't_ break.
 All
 that I know from the test program is that rounding modes and exceptions
 are
 not preserved.  If this is the only thing that is not preserved, then a
 program
 that (a) never changes the rounding direction, and (b) never inspects the
 floating exceptions should be unaffected.

 But note: many common operations change the rounding direction and you
 might
 not even realize it!  For example: a common way to implement "round to
 integer
 towards negative infinity" (i.e. the "floor" function in C, or
 "roundToIntegralTowardNegative" in IEEE parlance) efficiently on the x87
 is by
 code somewhat like the following:
 {{{
   x <- get rounding mode
   set rounding mode to towards negative infinity
   round to integer (according to the current rounding direction)
   set rounding mode to x
 }}}
 On these systems, a foreign call to "floor" would probably do something
 like
 the above.  On the other hand, I *think* the runtime won't pre-empt
 foreign
 calls so we may be OK (the documentation is not clear what happens if a
 signal arrives in the middle of this, though...).

 > If your program ''does'' write the rounding mode register or read from
 the
 > exception register, then this behavior of `forkIO` is not the only
 problem
 > you'll have: the Prelude exports the floating point arithmetic
 operations as
 > pure functions, even though they depend on the rounding mode and can
 raise
 > exceptions.  This obviously breaks referential transparency

 You are right that the "pure" nature of the prelude functions is
 problematic.
 However, in this case we can, with some care, control the evaluation
 order:
 I don't think that the problems are much worse than those of
 unsafePerformIO.

 > and compiler optimizations

 I would consider any compiler optimization that prevents floating point
 from
 working reliably to be a separate bug orthogonal to this issue.

 Note that such optimizations are usually problematic even if the program
 does
 not touch the rounding mode or exceptions, because they can affect the
 stability of an algorithm.

 > so you could say that even the Prelude is "broken" under these
 conditions.

 The Prelude has an awful lot of problems with respect to floating point,
 but
 I don't think they have anything to do with this particular issue.

 > Asking "how much code on hackage is broken in this regard" is
 meaningless,
 > unless you think there a lot of code on hackage which goes and mucks
 with the
 > floating point state on unsuspecting programs (seems unlikely to me).

 Almost every floating point operation potentially mucks with the floating
 point
 state, because almost every operation can raise exceptions.  If an unbound
 thread _anywhere_ in the program raises an exception, it becomes
 impossible
 to reliably inspect the floating point exception state _anywhere_ in the
 program.  I suspect that there may be packages on Hackage which use
 unbound
 threads and floating point, and the implications are that any program
 which
 uses those packages (perhaps transitively) would be unable to rely on
 floating point exceptions working, even if their code is otherwise
 perfect.

 Unlike the case with secretly-impure functions, I'm not aware of any way
 to
 control the way in which threads are pre-empted or migrated.

 > It would be nice to mention in the documentation, maybe in section
 "12.1.2.
 > GHC's interpretation of undefined behaviour in Haskell 98" under
 "Unchecked
 > float arithmetic", that GHC does not manage the floating point rounding
 or
 > exception registers in any way; in particular, they are not saved or
 restored
 > by Haskell thread switches, and accessing them directly in conjunction
 with
 > using built-in floating point operations causes undefined behavior.

 That would be a very unfortunate limitation as it goes well beyond "don't
 use
 floating point in unbound threads".

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4391#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to