2013-05-31 63 views
0

我有一個Python Pyro4遠程對象的問題,其行爲就好像它們是死鎖一樣。以下是如何重現問題(在Windows中)。啓動名稱服務器:Python Pyro4遠程對象塊(如果它是死鎖的)

set PYRO_HMAC_KEY=some_key 
python -m Pyro4.naming 

然後運行遠程對象服務器:

import Pyro4 
import sys 


class Scheduler: 
    def test(self): 
     pass 

if __name__ == '__main__': 

    sys.excepthook = Pyro4.util.excepthook 

    scheduler = Scheduler() 

    Pyro4.config.HMAC_KEY='some_key' 

    deamon = Pyro4.Daemon() 
    ns = Pyro4.locateNS() 
    ns.register("scheduler", deamon.register(scheduler)) 

    deamon.requestLoop() 

然後運行客戶端:

import sys 
from multiprocessing import Process 
import Pyro4 

class BWModule(Process): 

    def __init__(self): 
     Process.__init__(self) 
     self.depth = 1 


    def run(self): 

     Pyro4.config.HMAC_KEY='some_key'  
     self.scheduler = Pyro4.Proxy("PYRONAME:scheduler")     

     print "1" 
     sys.stdout.flush()   
     self.scheduler.test() 
     print "2" 
     sys.stdout.flush()   

     print "depth", self.depth 
     sys.stdout.flush() 

     if self.depth < 5: 
      for i in range(10): 
       newblock = self.duplicate() 
       newblock.depth = self.depth + 1 
       newblock.start() 


    def duplicate(self): 
     dup = type(self)() 
     return dup 



if __name__ == '__main__': 

    sys.excepthook = Pyro4.util.excepthook 

    No1 = BWModule()  
    No1.start() 

當運行該代碼,我看到印刷信息「深度X「,X從1到3但不多。我還看到在執行結束時(在沒有其他事情發生之前)一堆1沒有相應的2s,這表明調用Pyro遠程對象「self.scheduler.test()」已被阻止。這讓我認爲這是Pyro的問題,而不是流程(例如,如果可能的話,可用的流程將用完)。但是,如果我將進程乘法從10減少到2(即在範圍(2):「在客戶端代碼中」替換「對於範圍(10):」中的i)「,則執行一直到深度5沒有阻塞...

所以這裏是我的問題:什麼是happining?爲什麼它會阻止「爲我在範圍(10):」?對於Pyro4遠程對象或類似的東西是否有可能的「客戶端」進程的限制?這是一個死鎖問題嗎?

謝謝。

回答

1

好的。對於任何面臨類似問題的人來說,這個問題似乎與Pyro代理數量的限制有關,這些代理可以同時持有遠程對象的引用。但要小心,我只是在猜測這個。這一結論是基於這樣的事實,加上

del self.scheduler 

權利之前

if self.depth < 5: 
在客戶端代碼

兩個限制活着代理的數量,解決了這個問題(給它足夠的時間,代碼上去使用「for i in range(10):」來深度5。

編輯:

據我所知從here和一些測試,THREADPOOL_MINTHREADS的值被鏈接到連接或代理的最大數目對遠程對象。如果將其設置爲4,則當第五個代理嘗試訪問我的遠程對象時,程序會凍結(就像死鎖一樣)。

還有一些可能的相關信息here

0

就遇到過類似的問題,一個更合適的方法來做到這一點可能會改變

self.scheduler = Pyro4.Proxy("PYRONAME:scheduler") 

with Pyro4.Proxy("PYRONAME:scheduler") as self.scheduler: 
    # Rest of code using self.scheduler 
#Rest of code not using self.scheduler 

這相當於使用del self.scheduler除非你不必擔心你放置它的地方 - python爲你做了繁重的工作。