Hi all,

Please find attached a self contained program, which is supposed to run
a useless thread for 3 seconds, kill it (logging a notice about an
exception being caught), create some garbage (logging a notice before
and afterwards) and exit properly.

To compile:
$ csc -o ttm ttm.scm

Here's the output on my machine:

$ ./ttm 
test
Load error in (define aa (with-timeout 3 (lambda () (do () (#f)
#t)))):(timeout) in (define aa (with-timeout 3 (lambda () (do () (#f)
#t))))
let's do some garbage
Segmentation fault
$ ./ttm 
test
Load error in (define aa (with-timeout 3 (lambda () (do () (#f)
#t)))):(timeout) in (define aa (with-timeout 3 (lambda () (do () (#f)
#t))))
let's do some garbage

out of memory - heap full while resizing - execution terminated

...more...
ttm.scm: 66   number->string
ttm.scm: 66   string-append
ttm.scm: 66   number->string
ttm.scm: 66   string-append
ttm.scm: 66   number->string
ttm.scm: 66   string-append
ttm.scm: 66   number->string
ttm.scm: 66   string-append     <--
$ ./ttm 
test
Load error in (define aa (with-timeout 3 (lambda () (do () (#f)
#t)))):(timeout) in (define aa (with-timeout 3 (lambda () (do () (#f)
#t))))
let's do some garbage
Segmentation fault
$ ./ttm 
test
Load error in (define aa (with-timeout 3 (lambda () (do () (#f)
#t)))):(timeout) in (define aa (with-timeout 3 (lambda () (do () (#f)
#t))))
let's do some garbage

out of memory - heap full while resizing - execution terminated

...more...
ttm.scm: 66   number->string
ttm.scm: 66   string-append
ttm.scm: 66   number->string
ttm.scm: 66   string-append
ttm.scm: 66   number->string
ttm.scm: 66   string-append
ttm.scm: 66   number->string
ttm.scm: 66   string-append     <--
$ ./ttm 
test
Load error in (define aa (with-timeout 3 (lambda () (do () (#f)
#t)))):(timeout) in (define aa (with-timeout 3 (lambda () (do () (#f)
#t))))
let's do some garbage
Segmentation fault

Best regards

/Jörg
(declare (uses srfi-18)
	 (run-time-macros))

(define-macro (guard . form)
  (let* ((clause (or (and (pair? form) (car form))
                     (error "guard: syntax error in" form)))
         (body (cdr form))
	 (condition (gensym))
	 (handler-k (gensym))
	 (return (gensym))
	 (oldh (gensym)))
    `((call-with-current-continuation
       (lambda (,return)
	 (let ((,oldh (current-exception-handler)))
	   (with-exception-handler
	    (lambda (,condition)
	      (with-exception-handler
	       ,oldh
	       (call-with-current-continuation
		(lambda (,handler-k)
		  (,return (lambda ()
			    ((lambda (,(car clause))
			       ,(let loop ((clauses (cdr clause)))
				  (if (null? clauses)
				      `(raise ,(car clause))
				      (let ((c (car clauses)))
					(cond
					 ((eq? 'else (car c))
					  (if (null? (cdr c))
					      '#f
					      (if (null? (cddr c))
						  (cadr c)
						  `(begin . ,(cdr c)))))
					 ((and (pair? c) (pair? (cdr c)) (eq? '=> (cadr c)))
					  (let ((v (gensym)))
					    `(let ((,v ,(car c)))
					       (if ,v (,(caddr c)) ,(loop (cdr clauses))))))
					 ((and (pair? c) (null? (cdr c)))
					  (let ((v (gensym)))
					    `(let ((,v ,(car c)))
					       (if ,v ,v ,(loop (cdr clauses))))))
					 ((pair? c)
					  `(if ,(car c)
					       ,(if (null? (cddr c))
						    (cadr c)
						    `(begin . ,(cdr c)))
					       ,(loop (cdr clauses))))
					 (else (error "guard syntax error in ~a" c)))))))
			     ,condition)))))))
	    (lambda ()
	      (##sys#call-with-values
	       (lambda ()
		 ,(if (and (pair? body) (null? (cdr body)))
		      (car body) `(begin . ,body) ))
	       (lambda args
		 (,return (lambda () (##sys#apply ##sys#values args)))) ) ) )) ) ))))

(define (logerr . args)
  (apply format (current-error-port) args)
  (flush-output (current-error-port))
  (format (current-error-port) "let's do some garbage\n")
  (flush-output (current-error-port))
  (let ((s ""))
    (do ((i 0 (+ i 1)))
	((eqv? i 20000) #t)
      (set! s (string-append s (number->string i)))))
  (format (current-error-port) "enough garbage\n")
  (flush-output (current-error-port)))

(define *local-timeout-symbol* '(timeout))

(define (timeout-object) *local-timeout-symbol*)

(define (timeout-object? obj)
  (eq? *local-timeout-symbol* obj))

(define (with-timeout timeout thunk)
  (if timeout
      (let ([thread (thread-start! (make-thread thunk
						;; (string-append (thread-name (current-thread)) "-worker")
						))])
	(guard
	 (condition
	  ((join-timeout-exception? condition)
	   (thread-terminate! thread)
	   (raise (timeout-object)))
	  (else
	   (raise (if (uncaught-exception? condition)
		      (uncaught-exception-reason condition)
		      condition))))
	 (thread-join! thread timeout)))
      (thunk)))

(define (load-or-die str)
  (guard
   (exception (else (logerr "Fatal load error in ~a:~s ~a\n" file ((condition-property-accessor 'exn 'message #f) exception) ((condition-property-accessor 'exn 'arguments #f) exception))
                    (exit 0)))
   (call-with-input-string str
     (lambda (port)
       (let loop ((expr (read port))
                  (last #f))
         (if (eof-object? expr)
             last
             (loop (read port)
                   (guard
                    (ex (else (logerr "Load error in ~a:~a in ~a\n"
                                      str ex expr) #f))
                    (eval expr)))))))))

(print "test")
(load-or-die "(define aa (with-timeout 3 (lambda () (do () (#f) #t))))")
(logerr "done\n")
(exit 0)
_______________________________________________
Chicken-users mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/chicken-users

Reply via email to