with-timeout is broken when using (gc-logfile)

Bug #1754785 reported by Andrew Berkley on 2018-03-10
This bug affects 1 person
Affects Status Importance Assigned to Milestone

Bug Description

The problem is that the post-gc hooks are wrapped with a handler-case that ignores serious-conditions and run in the thread that triggered the gc (I think). So anything that does asynchronous delivery of signals (for example with-timeout, interrupt-thread, etc) will suffer from missed signals once in awhile (notably if the timeouts are shorter than the gc time).

Here is code to reproduce the problem on sbcl 1.3.0:

(defparameter *blarg* nil)

(defun test-timeout (&optional (tries 30))
  (let ((fail nil))
    (labels ((check ()
               (let ((iterations 0))
                 (loop :until (or fail (>= iterations 100))
                    (block test-block
                      (incf iterations)
                          ((timeout (lambda (e) (declare (ignore e)) (setf fail nil) (return-from test-block))))
                        (with-timeout 0.1
                          (setf *blarg* (make-array 1000000))
                          (sleep 2)
                          (setf fail t))))))))
  (format t "Trying with gc-logfile off: ")
  (setf (gc-logfile) nil)
  (dotimes (x tries) (check))
  (format t "~A~%" (if fail "FAIL" "PASS"))
  (setf (gc-logfile) "/tmp/blarg")
  (format t "Trying with gc-logfile on: ")
  (dotimes (x tries) (check))
  (format t "~A~%" (if fail "FAIL" "PASS")))))

CL-USER> (test-timeout)
Trying with gc-logfile off: PASS
Trying with gc-logfile on:
Problem running after-GC hook #<CLOSURE SB-KERNEL::LOG-GC-REPORT-TO-FILE>:
Timeout occurred.

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers