[Pythonmac-SIG] Python threading.Thread vs PyObjC performOnMainThread

gandreas@gandreas.com gandreas at gandreas.com
Mon May 16 18:35:14 CEST 2005


So I'm reworking how debugging is handled in PyOXIDE and I've come to  
a problem (several, but this is the biggy for the morning).

My goal is to separate interacting with the (remote) debugged client  
in a separate thread, which forwards messages to the main thread as  
needed to run the debugger UI (since all UI must be done on the main  
thread).

The code is:
def runThreadDebugSession(connection):
     from Foundation import NSAutoreleasePool
     pool = NSAutoreleasePool.alloc().init()
     from  Foundation import NSLog

     try:
         debugger = None
         while connection.ClientAlive():
             NSLog("Servicing threaded debug client")
             what  = connection.ServiceClient()
             NSLog("Serviced " + what)
             if connection.IsStopped():
                 NSLog("Remote client stopped - getting debugger")
                 remoteDebugger = connection.GetDebugger()
                 NSLog("got debugger")
                 if debugger == None:  # first time, make the debugger
                     NSLog("building debugger")
                     debugger = PyDebuggerController.alloc()
                      
debugger.performSelectorOnMainThread_withObject_waitUntilDone_ 
("initWithDebugger:",PyRemoteDebugger(debugger, remoteDebugger,  
connection),True)
                      
debugger.performSelectorOnMainThread_withObject_waitUntilDone_ 
("startWithUserLine_",remoteDebugger.curframe)
         NSLog("Client no longer alive")
     except:
         import sys,traceback
         traceback.print_exc()
         pass # something went away

def spawnRemoteDebugger(connection):
     # when we get a remote debugger, spawn off in another thread
     import threading
     thread = threading.Thread(target = runThreadDebugSession, args= 
(connection,))
     thread.start()


When the user says "debug", we launch the separate processes, which  
includes a stub to open up a TCP connection back to the IDE, which we  
use to interact with on the main event loop (which was ugly, since it  
would then nest, well, it was ugly).  So now I call the above  
"spawnRemoteDebugger", it talks with the targeted process, and then  
at some point that process says "hey, let's start debugging" (and  
transfers over a proxy object to allow the IDE to interact with  
something that looks like a pdb object).  That's all more or less fine.

The problem is that we then allocate and init the debugger controller  
(PyDebuggerController).  Since that needs to be done on the main  
thread, we use performSelectorOnMainThread.  That works fine except  
that when this debugger controller object gets created, it eventually  
wants to call the python code associated said object.  Of course,  
since that's on the main thread (and not this other debugger handler  
thread) it calls PyThread_aquire_lock.  But the lock is stuck in the  
thread that executing the performSelectorOnMainThread line, and  
everything just stops (the main thread waits on the semaphore which  
will never be released).

So, it appears that performSelectorOnMainThread needs some way to  
release the lock to let Python code in the main thread be executed.   
Any suggestions for workarounds?


Glenn Andreas                      gandreas at gandreas.com
  <http://www.gandreas.com/> oh my!
quadrium | build, mutate, evolve | images, textures, backgrounds, art

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/pythonmac-sig/attachments/20050516/4aa458d2/attachment.htm


More information about the Pythonmac-SIG mailing list