racket / ChezScheme

Chez Scheme
Apache License 2.0
110 stars 8 forks source link

invalid dirty byte with set-car! of weak pair #64

Closed burgerrg closed 1 year ago

burgerrg commented 1 year ago
(parameterize ([collect-request-handler void]
               [collect-maximum-generation (max (collect-maximum-generation) 2)]
               [#%$enable-check-heap #t])
  (let ([key "key"])
    (let ([e (weak-cons key #f)])
      (collect 0 1 1)
      (let ([key2 (gensym key)])
        (printf "before:         e = ~s\n" e)  
        ;; e is gen 1, key2 is gen 0:
        (set-car! e key2)
        (printf "after set-car!: e = ~s\n" e)  
        (collect 1 1 2)
        (printf "after collect:  e = ~s\n" e)  
        ;; Now, e is gen 1, key2 is gen 0
        (and (eq? (car e) key2)
             (begin
               (printf "before next collect: e = ~s\n" e)
               (collect 1 2 2)
               (printf "after next collect: e = ~s\n" e)
               ;; Check that the GC update the reference to `key2` in `e`:
               (eq? (car e) key2)))))))

The code above results in:

Petite Chez Scheme Version 9.9.9-pre-release.18
Copyright 1984-2022 Cisco Systems, Inc.

> (cd "~/Downloads")
> (load "bug.ss")
before:         e = ("key" . #f)
after set-car!: e = (#{key h9paif7rj8tubsf58g82k3v3g-0} . #f)
!!! INVALID dirty byte 255 found in segment 0x40667, card 0 at 0x10199c000
from segment 0x40667 si=0x101a72fc0 generation=2 space-weakpr
to   segment 0x40669 si=0x101a73100 generation=1 space-symbol
!!! INVALID dirty byte 255 found in segment 0x40667, card 0 at 0x10199c000
from segment 0x40667 si=0x101a72fc0 generation=2 space-weakpr
to   segment 0x40669 si=0x101a73100 generation=1 space-symbol
heap check failed after gc

Many thanks to Oscar Waddell for tripping the bug and finding a succinct way to reproduce it. It occurs in Chez Scheme 9.5.8 as well and seems to be related to the change to incremental generation promotion. (Matthew, thanks for the ephemeron-cons test in 4.ms, which Oscar copied to use weak-cons instead.)

mflatt commented 1 year ago

Looks like the problem is that resweeping weak pointers via forward_or_bwp needs to be more like relocate_impure_help_help instead of relocate_pure_help_help: check the "from" and "to" generations and potentially record a new dirty card. I have a candidate repair, but will test more before pushing.

burgerrg commented 1 year ago

Thank you!