#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