Prev: Call for papers (Deadline Extended): AIPR-10, USA, July 2010
Next: Reading *standard-input* as a byte stream
From: Johan Ur Riise on 26 Mar 2010 21:22 Peter Keller <psilord(a)merlin.cs.wisc.edu> writes: > Johan Ur Riise <johan(a)riise-data.no> wrote: >> I think that in general, you should not rely on automatic releasing of >> resources. I think each thread should fall off the end of its thread >> function (it doesn't really return). You should make sure that sockets >> and files are closed, either by calling close or use with-open-file or >> something, before you leave them for garbage collection. This is the >> same in all languages. > > This is true, but if the thread is something like an echo server to a client > then until the client sends a pre-agreed upon sentinel value, the thread > will sit there happily copying bytes without any way to stop it. If you ask for data and wait indefinitely, that is what you get. The WITH-TIMEOUT abstraction is built on the operating system's signal system. It asks the kernel to send a signal to the process after the requested amount of time. The signal interrupts the blocking system call and causes a signal handler to be executed, which takes you back into lisp. Is not that what you want? You could probably build something yourself using signals, but you are moving further away from lisp. > Well, there > is a way with your method before, via inspecting a global *stop* variable, > but even that has peril and it still isn't an active close from the point of > view of the client. I do not understand why this method is not active enough. Maybe you should start over and take a look at nonblocking asynchronous sockets. > > I actively want to clean up all of my non-memory resources, but killing > threads allows for situations where unwind-protect won't function, > thereby voiding the semantics of unwind-protect. Why did you ever expect the unwind-protect form to continue its work after the thread where it runs is killed? If you want to kill the thread and have an API for that, use it, and hope that the operating system does what is needed for you. I suspect you run out of file handles after a while, but what do I know. > >> About the variable *client* - most implementations treat the global >> special variables as common between all threads, useful for >> communication between threads. > > That is true. But, in my haste I did not mention that I am using the > bordeaux threads special mechanism of creating thread specific global > bindings with *default-special-bindings*. It is there that I would set > up *client* bound to the client socket before starting the thread. In this > manner is *client* specific to each thread. Ok, I was not aware of that mechanism.
From: Peter Keller on 27 Mar 2010 00:15 Johan Ur Riise <johan(a)riise-data.no> wrote: > If you ask for data and wait indefinitely, that is what you get. The > WITH-TIMEOUT abstraction is built on the operating system's signal > system. It asks the kernel to send a signal to the process after the > requested amount of time. The signal interrupts the blocking system > call and causes a signal handler to be executed, which takes you back > into lisp. Is not that what you want? It is, but WITH-TIMEOUT seems to be SBCL specific and I was looking for portability and staying as close to ANSI Common Lisp as possible. > I do not understand why this method is not active enough. Maybe you > should start over and take a look at nonblocking asynchronous sockets. The threading code I'm writing is part of a larger set of examples where eventually multiplexed nonblocking socket I/O is utilized and the threading model goes away. > Why did you ever expect the unwind-protect form to continue its work > after the thread where it runs is killed? http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/speope_unwind-protect.html That page implies the reading which I presented. Since I wasn't using a non-local exit as specified in the definition of that term, I thought it would work. It somewhat goes against sense that I could kill a thread and yet somehow the unwind-protect cleanup form would still fire, but breaking into the debugger and asking to abort the computation of a protected form didn't seem that far away conceptually from destroying a thread. > If you want to kill the thread and have an API for that, use it, and > hope that the operating system does what is needed for you. I suspect > you run out of file handles after a while, but what do I know. The one thing you definitely have taught me is that threading in Common Lisp is Hard. :) If I can't eagerly clean up non-memory resources perfectly then I'll run out at some point... But I think I know what to do now for my code and my explanation of it. I would like to thank you for our conversation and I appreciate your time. Later, -pete
From: Johan Ur Riise on 27 Mar 2010 05:06 Peter Keller <psilord(a)merlin.cs.wisc.edu> writes: > Johan Ur Riise <johan(a)riise-data.no> wrote: >> >> Why did you ever expect the unwind-protect form to continue its work >> after the thread where it runs is killed? > > http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/speope_unwind-protect.html > > That page implies the reading which I presented. Since I wasn't using a > non-local exit as specified in the definition of that term, I thought it > would work. It somewhat goes against sense that I could kill a thread and > yet somehow the unwind-protect cleanup form would still fire, but breaking > into the debugger and asking to abort the computation of a protected > form didn't seem that far away conceptually from destroying a thread. Destroying a thread is like someone coming into your computer room with a big axe and destroying your machine. Two threads are like two different programs, they just happen to share some data, not too much different than two programs reading the same file, or two computers downloading the same file from the internet, in this sense. If the authors of the page you referred to thaught about threads at all when they wrote it, I think they regarded it as self evident that the cleanup form would have to execute in the same thread. Maybe you want this: Keep a list of sockets and id of the thread where each socket are used somewhere global, then after you kill a process from outside, you find the sockets belonging to that thread and close them. That is cleanup from another thread, but I do not know why this would be better.
First
|
Prev
|
Pages: 1 2 3 4 Prev: Call for papers (Deadline Extended): AIPR-10, USA, July 2010 Next: Reading *standard-input* as a byte stream |