Re: thread resource leaks if thread terminates with uncaught exception
Jens Thiele <[email protected]> Thu, 09 Jan 2025 09:25:23 +0100
| Newsgroups | gmane.lisp.scheme.gauche |
|---|---|
| Message-ID | <[email protected]> |
Jens Thiele <[email protected]> writes: > Slightly off-topic/different topic (but this is how I ended up here): > it looks like pmap with the fully-concurrent-mapper doesn't join all > threads in run-map in the case where proc raised an error. the reverse proxy example using pmap: #!/bin/sh #| -*- mode: scheme; coding: utf-8; -*- #export GC_PRINT_STATS=1 exec gosh -I. -- $0 "$@" |# (use makiki) (use text.html-lite) (use rfc.http) (use gauche.threads) (use file.util) (use gauche.sequence) (use control.pmap) ;; todo: linux specific (define (num-open-files) (guard (e [else +nan.0]) (length (directory-list "/proc/self/fd" :children? #t)))) (define (num-threads) (guard (e [else +nan.0]) (length (directory-list "/proc/self/task" :children? #t)))) (define-http-handler (GET) "/" (^[req app] (receive (status headers body) (http-get "localhost:8081" "/") (respond/ok req body)))) (define (http-get-body) (receive (status headers body) ;; todo: detect host name and use it to force a real ;; dns lookup to occur? (http-get "localhost:8081" "/slow") body)) (define-http-handler (GET) "/timeout" (lambda(req app) (let1 r (guard (e [(uncaught-exception-condition? e) #?=(uncaught-exception-condition-reason e)] [else #?=e]) (pmap (lambda(i) (http-get-body)) (iota 400) :mapper (make-fully-concurrent-mapper 0.1 'timeout))) (cond [(and (list? r) (eq? (car r) 'timeout)) (respond/ok req (list (html-doctype) (html:html (html:head (html:title "timeout")) (html:body (html:p "timeout") (html:p (string-append (x->string (num-open-files)) " open files"))))))] [(list? r) (car body)] [else (request-error :body r)])))) (define (main args) #?=(sys-getpid) (debug-print-width 4000) (start-http-server :port 8080 :error-log #t) 0) I run it with setarch -R to "reduce the randomness" (the pointer addresses still vary between runs) like this: $ time setarch -R ./reverse-proxy-pmap.scm 2>&1|tee /tmp/log and get relatively early: #?="././reverse-proxy-pmap.scm":68:(sys-getpid) #?- 1648580 #?=[5]"././reverse-proxy-pmap.scm":44:(uncaught-exception-condition-reason e) #?-[5] #<system-error "getaddrinfo failed: System error: Device or resource busy"> WARNING: A thread #f (11848) died a lonely death with an uncaught exception #<system-error "getaddrinfo failed: System error: Device or resource busy">. WARNING: A thread #f (11830) died a lonely death with an uncaught exception #<system-error "getaddrinfo failed: System error: Device or resource busy">. WARNING: A thread #f (11849) died a lonely death with an uncaught exception #<system-error "getaddrinfo failed: System error: Device or resource busy">. WARNING: A thread #f (11839) died a lonely death with an uncaught exception #<system-error "getaddrinfo failed: System error: Device or resource busy">. WARNING: A thread #f (11850) died a lonely death with an uncaught exception #<system-error "getaddrinfo failed: System error: Device or resource busy">. ... WARNING: A thread #f (16812) died a lonely death with an uncaught exception #<system-error "getaddrinfo failed: System error: Device or resource busy">. *** SYSTEM-ERROR: accept(2) failed: Too many open files Stack Trace: _______________________________________ 0 (report-error e) 1 (socket-accept s) at "/usr/share/gauche-0.98/site/lib/makiki.scm":800 2 (proc (car xs)) 3 (for-each (^h (apply (car h) (cdr h))) (append (pick-handlers ... at "/usr/share/gauche-0.98/0.9.15/lib/gauche/selector.scm":121 4 (selector-select sel) at "/usr/share/gauche-0.98/site/lib/makiki.scm":819 5 (do () ((not (unbox looping))) (selector-select sel)) at "/usr/share/gauche-0.98/0.9.15/lib/gauche/common-macros.scm":104 expanded from (while (unbox looping) (selector-select sel)) at "/usr/share/gauche-0.98/site/lib/makiki.scm":819 6 thunk 7 (start-http-server :port 8080 :error-log #t) at "././reverse-proxy-pmap.scm":70 8 (main args) Best regards Jens