GC-unsafe SB-ALIEN string deporting
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Fix Released
|
Medium
|
Unassigned |
Bug Description
Translating a Lisp string to an alien string by taking a SAP to it
as done by the :DEPORT-GEN methods for C-STRING and UTF8-STRING
is not safe, since the Lisp string can move. For example the
following code will fail quickly on both cheneygc and pre-0.9.8.19
GENCGC:
(setf (bytes-
(define-
(loop
(let ((string "hello, world"))
(assert (zerop (strcmp string string)))))
(This will appear to work on post-0.9.8.19 GENCGC, since
the GC no longer zeroes memory immediately after releasing
it after a minor GC. Either enabling the READ_PROTECT_
#define in gencgc.c or modifying the example so that a major
GC will occasionally be triggered would unmask the bug.)
On cheneygc the only solution would seem to be allocating some alien
memory, copying the data over, and arranging that it's freed once we
return. For GENCGC we could instead try to arrange that the string
from which the SAP is taken is always pinned.
For some more details see comments for (define-
(c-string :deport-gen) ...) in host-c-call.lisp.
New test-case better at provoking this:
(declaim (inline strcmp))
(define-
(s1 (c-string :external-format :utf-8))
(s2 (c-string :external-format :utf-8)))
(defvar *run* t)
(defun test ()
(loop while *run*
do (let ((string #.(coerce "hello, world" 'base-string)))
(let ((test-thread (sb-thread:
(
(sb-thread:
(sb-thread:
Even if the test-case seems to run nicely, interrupting it is likely to result
in a memory fault, and trying to recompile test test-case ends up in LDB.
Changed in sbcl: | |
importance: | Undecided → Medium |
status: | New → Confirmed |
importance: | Medium → High |
description: | updated |
description: | updated |
Changed in sbcl: | |
importance: | Undecided → High |
status: | New → Confirmed |
Changed in sbcl: | |
status: | Fix Committed → Fix Released |
Marking as NEW again while waiting for a chance to replicate this.