Skip to content

forkIO threads do not properly save/restore the floating point environment

When using forkIO threads, the floating point environment is not correctly saved and/or restored on context switches. This causes floating point state to leak between the threads.

For example, if two threads (call them A and B) are created, and thread A changes the rounding direction, computations in thread B will be carried out under the rounding direction set by A, and vice versa. Likewise, any exceptions raised by computations in thread A are visible in thread B.

If forkIO threads are not intended to be used with floating point, this should be spelled out explicitly in the documentation rather than some vague notion of avoiding "thread local state".

I've attached a short test program which demonstrates this issue. For portability, it uses standard C library functions to manipulate the floating point environment. It prints the following when compiled with GHC (parenthetical statements added):

A: ToNearest   (default rounding mode)
A: True
B: ToNearest
B: TowardZero
B: Infinity    (result of division by 0)
A: [DivByZero] (A sees B's exception)
A: TowardZero  (A sees B's rounding direction)
A: False

If we use OS threads (which properly save/restore the floating point environment):

A: ToNearest
A: True
B: ToNearest
B: TowardZero
B: Infinity   (result of division by zero)
A: []         (no new exceptions are visible)
A: ToNearest  (rounding direction is unchanged)
A: True
Trac metadata
Trac field Value
Version 6.12.3
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information