[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

at-exit-thread

Aaron Brady

2/29/2008 7:35:00 PM

The Python main interpreter has an at-exit list of callables, which
are called when the interpreter exits. Can threads have one? What's
involved, or is the best way merely to subclass Thread?
7 Answers

Diez B. Roggisch

2/29/2008 7:55:00 PM

0

castironpi@gmail.com schrieb:
> The Python main interpreter has an at-exit list of callables, which
> are called when the interpreter exits. Can threads have one? What's
> involved, or is the best way merely to subclass Thread?

Is that some sort of trick-question?


class MyThread(Thread):

def run(self):
while some_condition:
do_something()
do_something_after_the_thread_ends()

The atexit stuff is for process-termination which is/may be induced by
external signals - which is the reason why these callbacks extist.
Threads don't have that, thus no need.

Diez

Aaron Brady

2/29/2008 8:12:00 PM

0

On Feb 29, 1:55 pm, "Diez B. Roggisch" <de...@nospam.web.de> wrote:
> castiro...@gmail.com schrieb:
>
> > The Python main interpreter has an at-exit list of callables, which
> > are called when the interpreter exits.  Can threads have one?  What's
> > involved, or is the best way merely to subclass Thread?
>
> Is that some sort of trick-question?
>
> class MyThread(Thread):
>
>     def run(self):
>         while some_condition:
>              do_something()
>         do_something_after_the_thread_ends()
>
> The atexit stuff is for process-termination which is/may be induced by
> external signals - which is the reason why these callbacks extist.
> Threads don't have that, thus no need.

That depends. If a thread adds an object it creates to a nonlocal
collection, such as a class-static set, does it have to maintain a
list of all such objects, just to get the right ones destroyed on
completion? Processes destroy their garbage hassle-free; how can
threads? And don't forget Thread.run( self ) in the example, if
anyone ever wants to make use of the 'target' keyword.

Aaron Brady

2/29/2008 8:34:00 PM

0

On Feb 29, 2:12 pm, castiro...@gmail.com wrote:
> On Feb 29, 1:55 pm, "Diez B. Roggisch" <de...@nospam.web.de> wrote:
>
>
>
>
>
> > castiro...@gmail.com schrieb:
>
> > > The Python main interpreter has an at-exit list of callables, which
> > > are called when the interpreter exits.  Can threads have one?  What's
> > > involved, or is the best way merely to subclass Thread?
>
> > Is that some sort of trick-question?
>
> > class MyThread(Thread):
>
> >     def run(self):
> >         while some_condition:
> >              do_something()
> >         do_something_after_the_thread_ends()
>
> > The atexit stuff is for process-termination which is/may be induced by
> > external signals - which is the reason why these callbacks extist.
> > Threads don't have that, thus no need.
>
> That depends.  If a thread adds an object it creates to a nonlocal
> collection, such as a class-static set, does it have to maintain a
> list of all such objects, just to get the right ones destroyed on
> completion?  Processes destroy their garbage hassle-free; how can
> threads?  And don't forget Thread.run( self ) in the example, if
> anyone ever wants to make use of the 'target' keyword.- Hide quoted text -

Two snippets from the docs that are worrisome:

# If they invoke anything in threading.py that calls currentThread(),
they
# leave an entry in the _active dict forever after.
-threading.py

thread.get_ident()
... Thread identifiers may be recycled when a thread exits and another
thread is created.
-thread module doc

If you try to look up something by thread_id, you can get a terminated
thread's old resources. at-thread-exit could prevent it. What is the
scope of a resource a daemon thread allocates?

Preston Landers

2/29/2008 10:35:00 PM

0

On Feb 29, 2:12 pm, castiro...@gmail.com wrote:
> If a thread adds an object it creates to a nonlocal
> collection, such as a class-static set, does it have to maintain a
> list of all such objects, just to get the right ones destroyed on
> completion?  

Yes.

> Processes destroy their garbage hassle-free; how can
> threads?  

If you're asking "is there some automatic way to associate a external
resource with a thread so that it's deleted when the thread is done"
then the answer (to the best of my knowledge) is no. You would have
to take care of these details yourself once something outside your
thread got a reference to the resource. If you keep all references to
the resource inside the thread, then you can use the __del__ method of
the resource to take any cleanup actions.

Also, processes don't always "destroy their garbage hassle free" if
you consider inter process communication. For instance, if you create
an object in one process then serialize it and pass it to another
process through e.g. an XMLRPC call, there's no automatic way for the
other process to be notified that the originating process exited.
You'd have to build that feature in. Exact same thing with threads.

> And don't forget Thread.run( self ) in the example, if
> anyone ever wants to make use of the 'target' keyword.

I don't understand what you're referring to.

Aaron Brady

3/1/2008 6:03:00 AM

0

On Feb 29, 4:34 pm, Preston Landers <pland...@gmail.com> wrote:
> On Feb 29, 2:12 pm, castiro...@gmail.com wrote:
>
> > If a thread adds an object it creates to a nonlocal
> > collection, such as a class-static set, does it have to maintain a
> > list of all such objects, just to get the right ones destroyed on
> > completion?  
>
> Yes.
>
> > Processes destroy their garbage hassle-free; how can
> > threads?  
>
> If you're asking "is there some automatic way to associate a external
> resource with a thread so that it's deleted when the thread is done"
> then the answer (to the best of my knowledge) is no.  You would have
> to take care of these details yourself once something outside your
> thread got a reference to the resource. If you keep all references to
> the resource inside the thread, then you can use the __del__ method of
> the resource to take any cleanup actions.
>
> Also, processes don't always "destroy their garbage hassle free" if
> you consider inter process communication.  For instance, if you create
> an object in one process then serialize it and pass it to another
> process through e.g. an XMLRPC call, there's no automatic way for the
> other process to be notified that the originating process exited.
> You'd have to build that feature in.  Exact same thing with threads.
>
> > And don't forget Thread.run( self ) in the example, if
> > anyone ever wants to make use of the 'target' keyword.
>
> I don't understand what you're referring to.

In the initial counterexample,

> class MyThread(Thread):
>
> def run(self):
> while some_condition:
> do_something()
> do_something_after_the_thread_ends()

, MyThread overrides 'run', so target is never called. It did create
the picture to me though that:

class MemHoldingThread( Thread ):
def __init__( self, *a, **kwa ):
Thread.__init__( self, *a, **kwa )
self.objs= set()
self._args= ( self, )+ self._args
def hold( self, obj ):
self.objs.add( obj )
return obj
def run( self ):
Thread.run( self )
self._cleanup()
def _cleanup( self ):
for obj in self.objs:
obj.clean()

Then,

def f( thd ):
resrc= thd.hold( NewResource() )
infinite_loop( resrc )

MemHoldingThread( target= f )

thd is prepended to f's list of arguments so that it has a handle to
its own thread object, but doesn't need an entire thread class--
middle ground. Then thd.hold adds any obj created to a thread-local
set (and returns it). Then, _cleanup iterates over the set, and calls
clean() on its items when f returns.

At this point, I've gotten really really complicated. Not only have I
still not shown the _at_exit call to MemHoldingThread static member
_clean_all_remaining, but it's only useful if NewResource provides a
list of globals/externals that it "adds itself to", or a clean()
method to do them itself. But, you do get the benefit of not having
to store each global/external in a Thread subclass object-- it does
that for you-- as well as the benefit of being able to invoke the
behavior without explicit additional subclasses.

thing1= MemHoldingThread( target= thingf ); thing1.start()
daemon1= MemHoldingThread( target= daemonf ); daemon1.start()
server1= MemHoldingThread( target= serverf ); server1.start()

rather than

class Thing( Thread ):... thing1= Thing(); thing1.start()
class Daemon( Thread ):... daemon1= Daemon(); daemon1.start()
class Server( Thread ):... server1= Server(); server1.start()

, which is useful sometimes, if even only a negligible proportion of
them.

<digressions>
(Honestly, if Thread.start() returned self,

class Thing( Thread ):... thing1= Thing().start()

, or Thread( start= True ) launched it, that could go a long way, --
you just get keyword name collisions with target's parameters pretty
soon.)

What are the disadvantages to specifying an internal storage byte
order for conversion to a string to use mmap with, by the way?

And for all my seniors out there, you may be pleased to learn that I
no longer think that all of my general little 5-liners should go in
the standard library.
</digressions>

> you consider inter process communication. For instance, if you create
> an object in one process then serialize it and pass it to another
> process through e.g. an XMLRPC call, there's no automatic way for the
> other process to be notified that the originating process exited.

Maybe... but if all else fails you can pass the process ID in on
connection creation, and periodically check if it's still alive. Do
any Op. Sys.s have a OnProcTerminate( hproc, callback ) API? Sadly,
stdin IPC is before my time.

Windows actually even has ThreadSuspend and ThreadResume API; if
suspending threads (and raising exceptions in them from others)
threatens state consistency, what are their semantics?

Gabriel Genellina

3/1/2008 6:35:00 AM

0

En Fri, 29 Feb 2008 18:12:13 -0200, <castironpi@gmail.com> escribió:

> On Feb 29, 1:55 pm, "Diez B. Roggisch" <de...@nospam.web.de> wrote:
>> castiro...@gmail.com schrieb:
>>
>> > The Python main interpreter has an at-exit list of callables, which
>> > are called when the interpreter exits.  Can threads have one?  What's
>> > involved, or is the best way merely to subclass Thread?
>>
>> Is that some sort of trick-question?
>>
>> class MyThread(Thread):
>>
>>     def run(self):
>>         while some_condition:
>>              do_something()
>>         do_something_after_the_thread_ends()
>>
>> The atexit stuff is for process-termination which is/may be induced by
>> external signals - which is the reason why these callbacks extist.
>> Threads don't have that, thus no need.
>
> That depends. If a thread adds an object it creates to a nonlocal
> collection, such as a class-static set, does it have to maintain a
> list of all such objects, just to get the right ones destroyed on
> completion?

Yes, like any other objects. All threads in a process share the same
memory space; any thread can "see" any other created object, and the
general rules on reference counting apply: an object is destroyed when it
is no more referenced.
There are threading.local objects, which are specially designed to provide
per-thread storage; they are not shared among threads. (BTW, you should
use a threading.local instance instead of indexing by get_ident())

> Processes destroy their garbage hassle-free; how can
> threads? And don't forget Thread.run( self ) in the example, if
> anyone ever wants to make use of the 'target' keyword.

Any object created inside a thread will be destroyed when the last
reference to it is removed, as any other object. Threads are not special
in this regard.

--
Gabriel Genellina

Diez B. Roggisch

3/1/2008 5:14:00 PM

0

castironpi@gmail.com schrieb:
> On Feb 29, 1:55 pm, "Diez B. Roggisch" <de...@nospam.web.de> wrote:
>> castiro...@gmail.com schrieb:
>>
>>> The Python main interpreter has an at-exit list of callables, which
>>> are called when the interpreter exits. Can threads have one? What's
>>> involved, or is the best way merely to subclass Thread?
>> Is that some sort of trick-question?
>>
>> class MyThread(Thread):
>>
>> def run(self):
>> while some_condition:
>> do_something()
>> do_something_after_the_thread_ends()
>>
>> The atexit stuff is for process-termination which is/may be induced by
>> external signals - which is the reason why these callbacks extist.
>> Threads don't have that, thus no need.
>
> That depends. If a thread adds an object it creates to a nonlocal
> collection, such as a class-static set, does it have to maintain a
> list of all such objects, just to get the right ones destroyed on
> completion? Processes destroy their garbage hassle-free; how can
> threads? And don't forget Thread.run( self ) in the example, if
> anyone ever wants to make use of the 'target' keyword.

That is both totally unrelated to the original question and plain wrong.
Processes don't destroy their garbage themselves, not automagically or
anything. If you _want_, you can put atexit-handlers that do clean up
some stuff, but you'll have to equip them with the necessary context
yourself.

And a

kill -9 <pid>

won't run *anything* of your own code.

The OS is eventually responsible for cleaning up.

Diez