[GHC] #15038: Memory Corruption (strange closure type)

GHC ghc-devs at haskell.org
Tue May 1 04:53:58 UTC 2018


#15038: Memory Corruption (strange closure type)
-------------------------------------+-------------------------------------
        Reporter:  andrewthad        |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  highest           |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.4.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  Runtime crash     |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #9718             |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by osa1):

 Andrew,

 > It sounds like the crash I have been experiencing will be fixed in GHC
 8.6

 That's correct. I'm implementing a fix right now, it should be merged in a
 few days.

 > What I don’t fully grasp is the set of circumstances under which this
 error manifests itself.

 This error happens when:

 - You have a top-level definition that uses unboxed sums and is not CAFFY
 (i.e. does not reference to CAFs directly or transitively).

   Note that GHC as a result of optimisations can introduce top-level
 definitions so predicting whether you'll have such definitions is
 impossible from the source code.

 - Unboxed sums used in this top-level definition have unused fields. This
 happens when you have a sum with type

   ```
   (# Int# | Int #)
   ```

   Here you need 3 slots: a tag, an `Int#` and an `Int`, because pointer
 and non-pointer fields can't overlap (GC concerns). Now here are two terms
 and what they're compiled to:

   ```
   (# 1# | #) ===> (# 0#, 1#, UNUSED_POINTER #)
   (# | 1 #)  ===> (# 1#, UNUSED_INT#, 1 #)
   ```

   We don't want to leave these unused fields uninitialized (for various
 reasons, like safety and IIRC also has to do with Cmm code generation
 which used to panic when pointer field is left with uninitialized
 garbage), so we use something called `absentError`. `absentError` should
 not be CAFFY otherwise it would make everything transitively referring to
 it CAFFY (I think when we first implemented unboxed sums `absentError` was
 not CAFFY), and CAFFY objects need special treatment from code generator
 and garbage collector. This causes the problem because CAFFY-ness is
 calculated in an early stage than the pass that compiles unboxed sums to
 unboxed tuples, causing inconsistent CAFFY information.

 In summary if at least one of these conditions hold you're safe:

 - You don't have `UNUSED_POINTER` fields in your unboxed sum types
 - The functions that use unboxed sums are CAFFY

 I'd suggest updating to next GHC when it's released.

 Simon,

 > It's #9718, and I wonder if we should devote some effort to nailing it?
 It's not that hard, and the status quo is a continuing source of
 fragility.

 I can work on this.

 > That is pretty terrible. I suggest making a separate ticket and fixing
 it asap.

 I'll do that now. The new function/primop we'll use instead of
 `absentError` won't be CAFFY so it'll fix this ticket.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15038#comment:26>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list