Hi all, i wrote a simple echo server/client. To catch SIGCHLD signal, i install a signal handler before first `connect'. The problem is that when the client exits, the handler seems not called. Instead, upon a new client connected to the server, the handler will be called(due to last client's exit).
To summarize, ,----[ first client ] | $ guile -e main server.scm | server started on localhost:10000 | New client(#(2 2130706433 54570)) incomming | | $ guile -e main client.scm | connected to server | hi | hi | | $ `---- ,----[ second client ] | $ guile -e main server.scm | server started on localhost:10000 | New client(#(2 2130706433 47200)) incomming | child 16648 terminated | New client(#(2 2130706433 47201)) incomming | | $ guile -e main client.scm | connected to server | hey | hey | | $ `---- Can the signal handler be called as soon as the client exits? Attchments are testing codes. -- William Work continues in this area. -- DEC's SPR-Answering-Automaton
;; echo client (use-modules (ice-9 optargs)) (use-modules (ice-9 getopt-long)) (use-modules (ice-9 rdelim)) (define (hostname->ip hostname) "Convert HOSTNAME to its IP. e.g., (hostname->ip \"www.google.com\") => \"64.233.189.104\"" (inet-ntop AF_INET (car (hostent:addr-list (gethost hostname))))) (define (main args) (let* ((option-spec '((help (single-char #\h) (value #f)) (host (single-char #\H) (value #t)) (port (single-char #\p) (value #t)))) (options (getopt-long args option-spec))) (if (option-ref options 'help #f) (usage) (client (option-ref options 'host "localhost") (option-ref options 'port "10000"))))) (define (usage) (display "\ Usage: client.scm [OPTIONS] -h, --help show this help -H, --host=LOCALHOST remote address -p, --port=10000 remote port ") (exit 1)) (define (client host port) (let ((s (socket PF_INET SOCK_STREAM 0)) (host-ip (hostname->ip host)) (port-value (string->number port))) (connect s AF_INET (inet-pton AF_INET host-ip) port-value) (display "connected to server\n") (echo-loop s))) (define (echo-loop server-port) (let ((line (read-line (current-input-port) 'concat))) (while (not (eof-object? line)) (display line server-port) (display (read-line server-port 'concat)) (set! line (read-line (current-input-port) 'concat))) (close server-port))) ;;; client.scm ends here
;; echo server (use-modules (ice-9 optargs)) (use-modules (ice-9 format)) (use-modules (ice-9 getopt-long)) (use-modules (ice-9 rdelim)) (define (hostname->ip hostname) "Convert HOSTNAME to its IP. e.g., (hostname->ip \"www.google.com\") => \"64.233.189.104\"" (inet-ntop AF_INET (car (hostent:addr-list (gethost hostname))))) (define (main args) (let* ((option-spec '((help (single-char #\h) (value #f)) (host (single-char #\H) (value #t)) (port (single-char #\p) (value #t)))) (options (getopt-long args option-spec))) (if (option-ref options 'help #f) (usage) (server (option-ref options 'host "localhost") (option-ref options 'port "10000"))))) (define (usage) (display "\ Usage: server.scm [OPTIONS] -h, --help show this help -H, --host=LOCALHOST listening address -p, --port=10000 listening port ") (exit 1)) (define (server host port) (let* ((s (socket PF_INET SOCK_STREAM 0)) (host-ip (hostname->ip host)) (port-value (string->number port))) (setsockopt s SOL_SOCKET SO_REUSEADDR 1) (bind s AF_INET (inet-pton AF_INET host-ip) port-value) (listen s 5) (format #t "server started on ~a:~a\n" host port) (sigaction SIGCHLD (lambda (sig) ;; (let ((pid (car (waitpid -1 WNOHANG)))) ;; (while (> pid 0) ;; (format #t "child ~d terminated\n" pid) ;; (set! pid (car (waitpid -1 WNOHANG))))))) (format #t "child ~d terminated\n" (car (waitpid -1 WNOHANG))))) (while #t (let* ((client (accept s)) (client-port (car client))) (format #t "New client(~S) incomming\n" (cdr client)) (and (zero? (primitive-fork)) ; child (begin (close-port s) (echo-loop client-port) (primitive-exit))) (close-port client-port))))) (define (echo-loop port) "Read from PORT and send back." (let ((line (read-line port 'concat))) (while (not (eof-object? line)) (display line port) (set! line (read-line port 'concat))) (close-port port))) ;;; server.scm ends here
_______________________________________________ Guile-user mailing list Guile-user@gnu.org http://lists.gnu.org/mailman/listinfo/guile-user