From: Yang, Chul-woong
Subject: SBCL/Threaded Application Question
Date: 
Message-ID: <IFEUb.17745$S3.332178@news.bora.net>
Hi, everyone.

I'm building my 1st example lisp application :-)
in SBCL (x86).
It's just simple SMTP proxy, which runs in multi-thread model.
(based on A.Kreugar's thread skeleton, posted some times ago)
But due to my short knowledge and lack of experience, something goes wrong.

(1) threaded application stops arbitrarily.

i.e. When i run my program, i met following situation

$ sbcl --load proxy.lisp
..blahblah... (time elapased and some operation performed)
[1]+  Stopped                 sbcl --load proxy.lisp

$

At my viewpoints, it seems that threaded processes are waiting for something
from standard input port. but there are no such thing in my code.
(Thread communicates with given sockets only)

Any clue?

(2) I tried to cover error situation with macro

(defmacro handle-socket-errors (socket &body body)
  "Eat my socket when it fails."
  `(handler-case
    (progn ,@body)
    (end-of-file (condition)
                 (socket-close ,socket)
                 condition)
    (sb-bsd-sockets::socket-error (condition)
                                  (socket-close ,socket)
                                  condition)))


but I sometimes get

debugger invoked on a SB-INT:SIMPLE-STREAM-ERROR in thread 7528:
  couldn't read from #<FILE-STREAM for "a constant string" {925D249}>:
    Connection reset by peer

can above macro handle-socket-errors can yield above msgs?

(3) how to debug multi-threaded application in SBCL?
I can debug threaded C-application with GDB.
Please teach me starting points.

---
Yang, Chul-Woong
······@aratech.co.kr

----------------------------------------------------------------------
Based on A.Krueger's thread skeleton, code snipplet is
as follows.

(defun threaded-tcp-server (port handler)
  (declare (function handler))
  "All the connections you want."
  (with-tcp-socket sock
                   (setf (sockopt-reuse-address sock) t)
                   (socket-bind sock sb-bsd-sockets::inet-address-any port)
                   (socket-listen sock 10)
                   (loop
                    (multiple-value-bind (clientsocket peer) (socket-accept
sock)
                      (let ((thread (make-handler-thread clientsocket
handler peer)))
                        (format nil "Thread ~A dispatched for ~A.~%" thread
peer))))))

(defun spawn-tcp-server (port handler)
  (declare (function handler))
  "Background yourself a TCP server."
  (let ((server (lambda () (threaded-tcp-server port handler))))
    (let ((thread (make-thread server)))
      (format t "Server thread ~A started.~%" thread))))

defun proxy (sock peer)
  "connection proxy"
  (let ((from nil) (to nil))
    (handle-socket-errors sock
                          (let ((str (socket-make-stream sock :input t
:output t :buffering :none)))
                            (with-tcp-socket ssock
                                             (socket-connect ssock
*proxyhost* *proxyport*)
                                             (let ((sstr (socket-make-stream
ssock :input t :output t :buffering :none)))
                                               (do ()
                                                   ((null (and
(open-stream-p str) (open-stream-p sstr))))
                                                 (multiple-value-setq (from
to) (do-proxy-loop str sstr from to peer)))))))
    (force-output))
  (socket-close sock))

(spawn-tcp-server 25 #'proxy)

From: Yang, Chul-woong
Subject: Re: SBCL/Threaded Application Question
Date: 
Message-ID: <X4HUb.17751$S3.337473@news.bora.net>
Oops. I studied condition mechanism of CL and solved (2).
shame on myself.

Anyway, Please give an insight for (1) and (3).
Regards,

Yang, Chul-woong
······@aratech.co.kr

>
> I'm building my 1st example lisp application :-)
> in SBCL (x86).
> It's just simple SMTP proxy, which runs in multi-thread model.
> (based on A.Kreugar's thread skeleton, posted some times ago)
> But due to my short knowledge and lack of experience, something goes
wrong.
>
> (1) threaded application stops arbitrarily.
>
> i.e. When i run my program, i met following situation
>
> $ sbcl --load proxy.lisp
> ..blahblah... (time elapased and some operation performed)
> [1]+  Stopped                 sbcl --load proxy.lisp
>
> $
>
> At my viewpoints, it seems that threaded processes are waiting for
something
> from standard input port. but there are no such thing in my code.
> (Thread communicates with given sockets only)
>
> Any clue?
>
> (2) I tried to cover error situation with macro
>
> (defmacro handle-socket-errors (socket &body body)
>   "Eat my socket when it fails."
>   `(handler-case
>     (progn ,@body)
>     (end-of-file (condition)
>                  (socket-close ,socket)
>                  condition)
>     (sb-bsd-sockets::socket-error (condition)
>                                   (socket-close ,socket)
>                                   condition)))
>
>
> but I sometimes get
>
> debugger invoked on a SB-INT:SIMPLE-STREAM-ERROR in thread 7528:
>   couldn't read from #<FILE-STREAM for "a constant string" {925D249}>:
>     Connection reset by peer
>
> can above macro handle-socket-errors can yield above msgs?
>
> (3) how to debug multi-threaded application in SBCL?
> I can debug threaded C-application with GDB.
> Please teach me starting points.
>
> ---
> Yang, Chul-Woong
> ······@aratech.co.kr
>
> ----------------------------------------------------------------------
> Based on A.Krueger's thread skeleton, code snipplet is
> as follows.
>
> (defun threaded-tcp-server (port handler)
>   (declare (function handler))
>   "All the connections you want."
>   (with-tcp-socket sock
>                    (setf (sockopt-reuse-address sock) t)
>                    (socket-bind sock sb-bsd-sockets::inet-address-any
port)
>                    (socket-listen sock 10)
>                    (loop
>                     (multiple-value-bind (clientsocket peer)
(socket-accept
> sock)
>                       (let ((thread (make-handler-thread clientsocket
> handler peer)))
>                         (format nil "Thread ~A dispatched for ~A.~%"
thread
> peer))))))
>
> (defun spawn-tcp-server (port handler)
>   (declare (function handler))
>   "Background yourself a TCP server."
>   (let ((server (lambda () (threaded-tcp-server port handler))))
>     (let ((thread (make-thread server)))
>       (format t "Server thread ~A started.~%" thread))))
>
> defun proxy (sock peer)
>   "connection proxy"
>   (let ((from nil) (to nil))
>     (handle-socket-errors sock
>                           (let ((str (socket-make-stream sock :input t
> :output t :buffering :none)))
>                             (with-tcp-socket ssock
>                                              (socket-connect ssock
> *proxyhost* *proxyport*)
>                                              (let ((sstr
(socket-make-stream
> ssock :input t :output t :buffering :none)))
>                                                (do ()
>                                                    ((null (and
> (open-stream-p str) (open-stream-p sstr))))
>                                                  (multiple-value-setq
(from
> to) (do-proxy-loop str sstr from to peer)))))))
>     (force-output))
>   (socket-close sock))
>
> (spawn-tcp-server 25 #'proxy)
>
>
From: Christophe Rhodes
Subject: Re: SBCL/Threaded Application Question
Date: 
Message-ID: <squ1241uum.fsf@lambda.dyndns.org>
"Yang, Chul-woong" <······@dbserver.kaist.ac.kr> writes:

> (1) threaded application stops arbitrarily.
>
> i.e. When i run my program, i met following situation
>
> $ sbcl --load proxy.lisp
> ..blahblah... (time elapased and some operation performed)
> [1]+  Stopped                 sbcl --load proxy.lisp
>
> $
>
> At my viewpoints, it seems that threaded processes are waiting for something
> from standard input port. but there are no such thing in my code.
> (Thread communicates with given sockets only)
>
> Any clue?

Yes, this is (or was, depending on your view) an amusing interaction
between shells, process groups and signals.  It's been fixed in the
CVS version, which is due for release in a couple of weeks; in the
meantime, typing fg at the prompt gets it going again.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)