Testing how array-creation routines interact with continuations, and crashing when the user does something that "is an error".
Bradley Lucier
(08 Mar 2023 21:19 UTC)
|
Re: Testing how array-creation routines interact with continuations, and crashing when the user does something that "is an error". Marc Nieper-Wißkirchen (09 Mar 2023 08:33 UTC)
|
Re: Testing how array-creation routines interact with continuations, and crashing when the user does something that "is an error".
Bradley Lucier
(09 Mar 2023 18:30 UTC)
|
New tests for procedures when reinvoking continuations; fix crashes.
Bradley Lucier
(09 Mar 2023 22:02 UTC)
|
I think it is perfectly fine that the library crashes the system when one selects an "unsafe" mode of the implementation. After all, this is what is expected: By selecting an "unsafe" mode, I ask for maximal efficiency at the expense of comprehensive tests against programming errors. Am Mi., 8. März 2023 um 22:19 Uhr schrieb Bradley Lucier <xxxxxx@purdue.edu>: > > There are currently no tests in the test suite for how > > array-{copy|append|stack|decurry|block}[!]* > > interact with continuations, and I'd like to fix that, especially for > independent implementations of this SRFI. > > I started with (pp is pretty-print to the system output port): > > > (import (srfi 231)) > > (let* ((cont #f) > (call-cont #t) > (domain (make-interval '#(2 2))) > (A_ (lambda (i j) > (call-with-current-continuation > (lambda (c) > (if (= i j 0) > (set! cont c)) > 1)))) > (A (make-array domain A_)) > (array-list '())) > (set! array-list (cons (array-copy A) array-list)) > (pp 'printing) > (for-each (lambda (A) (pp (array->list* A))) array-list) > (if call-cont > (begin > (set! call-cont #f) > (cont 4))) > (pp (apply eq? array-list))) > printing > ((1 1) (1 1)) > printing > ((4 1) (1 1)) > ((1 1) (1 1)) > #f > > which works as expected. > > Replacing array-copy with array-copy! in this test causes the library to > crash when compiled in Gambit with safety checks removed: > > > (let* ((cont #f) > (call-cont #t) > (domain (make-interval '#(2 2))) > (A_ (lambda (i j) > (call-with-current-continuation > (lambda (c) > (if (= i j 0) > (set! cont c)) > 1)))) > (A (make-array domain A_)) > (array-list '())) > (set! array-list (cons (array-copy! A) array-list)) > (pp 'printing) > (for-each (lambda (A) (pp (array->list* A))) array-list) > (if call-cont > (begin > (set! call-cont #f) > (cont 4))) > (pp (apply eq? array-list))) > printing > ((1 1) (1 1)) > printing > Segmentation fault (core dumped) > > I didn't expect this, I just expected that the first and second elements > of array-list would be eq?. Running the library interpreted shows the > problem: > > > (load "generic-arrays.scm") > "/home/lucier/lang/scheme/srfi-231/srfi-231-temp/generic-arrays.scm" > > (let* ((cont #f) > (call-cont #t) > (domain (make-interval '#(2 2))) > (A_ (lambda (i j) > (call-with-current-continuation > (lambda (c) > (if (= i j 0) > (set! cont c)) > 1)))) > (A (make-array domain A_)) > (array-list '())) > (set! array-list (cons (array-copy! A) array-list)) > (pp 'printing) > (for-each (lambda (A) (pp (array->list* A))) array-list) > (if call-cont > (begin > (set! call-cont #f) > (cont 4))) > (pp (apply eq? array-list))) > printing > ((1 1) (1 1)) > *** ERROR IN #<procedure #2>, "generic-arrays.scm"@2534.42 -- (Argument > 2, k) Out of range > (vector-set! #(4 1 1 1) 5 1) > 1> > > Here is the code: > > ;; No checks needed, storage-class-setter is > vector-set! > (let ((body (%%array-body destination))) > (%%interval-for-each > (case (%%interval-dimension domain) > ((0) (let ((index initial-offset)) > (lambda () > (vector-set! body index (getter)) > (set! index (fx+ index 1))))) > ;; not necessary > ((1) (let ((index initial-offset)) > (lambda (i) > (vector-set! body index > (getter i)) > (set! index (fx+ index 1))))) > ((2) (let ((index initial-offset)) > (lambda (i j) > (vector-set! body index > (getter i j)) ;; <<<<<< problem > (set! index (fx+ index 1))))) > ((3) (let ((index initial-offset)) > (lambda (i j k) > (vector-set! body index > (getter i j k)) > (set! index (fx+ index 1))))) > ((4) (let ((index initial-offset)) > (lambda (i j k l) > (vector-set! body index > (getter i j k l)) > (set! index (fx+ index 1))))) > (else (let ((index initial-offset)) > (lambda multi-index > (vector-set! body index (apply > getter multi-index)) > (set! index (fx+ index 1)))))) > domain)) > > So I was using mutated state (the value of index) in a (perhaps vain) > attempt to speed things up, but this causes index to walk off the end of > the specialized array result's body the second time the continuation is > invoked. > > The specifications says "Don't do that!", don't invoke the continuation > of the argument array's getter more than once when calling array-copy!. > > On the other hand, I didn't expect the library to crash the system. > > Is this OK behavior, to crash when the user does something that "is an > error", or would it be better to try to catch all such instances while > possibly slowing down the general case? > > Brad