2012-05-12 20 views
0

剛剛找到了Queue模塊,它幫助我調整了pyftpdlib模塊。我正在運行一個非常嚴格的FTP服務器,我的目標是限制可上傳的文件名。這是爲了防止人們上傳任何他們想要的內容(它實際上是上傳客戶端的後端,而不是完整的FTP服務器)。python隊列沒有傳遞正確的數據

我有這樣的FTPServer的授權人:

def fetch_worlds(queue, username): 
    while queue.empty(): 
     worlds = models.World.objects.filter(is_synced=True, user__username=username) 
     print worlds 

     queue.put(worlds, timeout=1) 

class FTPAuthorizer(ftpserver.DummyAuthorizer): 

    def __init__(self): 
     self.q = Queue.Queue() 
     self.t = None # Thread 
     self.world_item = None 

    def has_perm(self, username, perm, path=None): 

     print "Checking permission\n" 

     if perm not in ['r','w']: 
      return False 

     # Check world name   
     self.t = threading.Thread(target=fetch_worlds, args=(self.q, username)) 
     self.t.daemon = True 
     self.t.start() 

     self.world_item = self.q.get() 

     print "WORLDITEM: %s" % self.world_item 

     if path is not None: 
      path = os.path.basename(path) 
      for world in self.world_item: 
       test = "{0}_{1}.zip".format(username, world.name) 
       if path == test: 
        print "Match on %s" % test 
        return True 

     return False 

我的問題是,在服務器啓動後,我第一次STOR文件,它最初的分貝呼聲,妥善得到所有的世界。但是當我添加另一個世界時(例如,設置一個is_synced=True,它仍然返回來自self.q.get()的舊數據。每次上傳文件時會調用has_perm(),並且它需要返回實時數據(以檢查文件是允許的)

例如,全新的服務器:

  1. STOR file.zip,self.q.get()回報<World1, World2>
  2. 更新通過其他方法等
  3. STOR file2.zip,裏面fetch_worlds數據庫, print worlds返回<World1, World2, World3>self.q.get()返回<World1, World2>

剛剛發現隊列模塊,它似乎會有幫助,但我無法獲得實施的權利。

(也可以不加標籤pyftpdlib

回答

0

我認爲這是可能發生在這裏:(?)

  1. has_perm被調用,你創建一個Thread,將查詢數據庫向隊列添加元素
  2. 在調用start之後,調用數據庫將需要一些時間
  3. 同時在您輸入的主線程中q.get將阻止。
  4. 數據庫調用完成,並將結果添加到隊列
  5. 並從隊列被阻擋q.get
  6. 隊列現在是空的被立即刪除再次,你的線程再次進入while循環並執行再次進行相同的查詢並將結果放入隊列中。
  7. 下一次撥打q.get將返回,而不是它所期望的。

你看,你可能在這裏有一個競爭條件,這已經是aparent事實上,你添加一些東西到一個循環中的隊列,而你沒有一個循環時拉。 你也假設你從隊列中得到的元素是你之前放到它上面的結果。這並不一定是真的。
如果您撥打has_perm兩次,這將導致兩個電話到fetch_worlds,並且queue.empty()檢查其中一個呼叫失敗的可能性。所以只有一個結果會被放入隊列中。現在你有兩個線程在等待q.get,但只有一個會得到結果,而另一個等待一個準備就緒。

has_perm看起來應該是一個封鎖的電話。

+0

線程只是試圖讓它(以某種方式)得到新的結果。如果我取出所有線程和隊列,並且在'if path is not None'之前只有db查詢,它仍然不會得到新的結果。我必須重新啓動服務器才能查詢新的東西。可能我誤解了所有這些工作,儘管我希望我想要的東西仍然可以實現。 – paimoe