2015-06-09 49 views
1

我已經創建了一個客戶端服務器程序(在Python中),其中客戶端(例如CMD)與服務器建立TCP連接,查詢有關特定進程的信息,以及如果進程消耗的內存超過閾值,服務器終止進程並重新啓動它,並終止客戶端連接。我能夠創建多個客戶端查詢不同的進程,當兩個或更多客戶端向服務器查詢SAME PROCESS時,問題就出現了。理想情況下,應該終止進程,重新啓動並終止兩個客戶端連接。 問題是客戶端的連接只有一個被終止,而其他客戶端繼續掛在連接上,即使該進程重新啓動,其他客戶端仍然掛起並且其連接永不終止。這是死鎖的問題嗎?爲什麼兩個線程訪問一個資源會導致一個線程崩潰?

我的參考代碼(以代碼的任何更改將不勝感激來處理這個問題)

# A CLIENT-SERVER ARCHITECTURE TO GET INFO ABOUT RUNNING PROCESSES ON THE SYSTEM 
from thread import * 
import threading 
import time 
import psutil 
import itertools 
import ctypes 
import string 
import os 
import sys 
import socket 
import subprocess 

exitFlag = 0 
#function returning the list of all the valid partitions of the system... 
def drives(): 
    drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives() 
    return list(itertools.compress(string.ascii_uppercase,map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1]))) 

def proc_info(conn,addr): # prints the process's info which match the keyword....... SERVER SIDE 
    conn.send('Welcome to the server\n') 
    name=[] 
    c=drives() 
    o=[] 
    t=0 
    m=0 
    while(t<len(c)): 
     o.append(str(c[t]+':\\')) 
     t=t+1 
    k=0 
    #o.reverse() 
    conn.send("Enter the key...\n") # for authentication purposes...e.g.here the key is 1 
    t=conn.recv(8) 
    if(t!='1'): #WRONG KEY....INVALID USER 
     conn.send("\nInvalid key..teminating the connection.....ABORT\n") 
     conn.close() 

    else: 
     r="" 
     conn.send("\nEnter the process keyword ..Press # @ the end ") # e.g. 'Sk' for Skype 
     d=conn.recv(65536) 
     while(d!='#'): 
        r=r+str(d) 
      d=conn.recv(65536) 
     for p in psutil.pids(): # iterates through all the pids of the processes obtained 
        try: 
         p1=psutil.Process(p) 
      if(r in p1.name()): 
          p2=p1.get_memory_info() 
          t=p1.name()+' ' 
          d=str(p)+' ' 
          conn.send(d)# prints the pid of the process 
          conn.send(t),# prints the name of the process 
          d=str(p2[0]/(1024*1024))+' ' 
          conn.send(d) # print memory in MB 
          conn.send('MB\t') 
          for connect in p1.connections(kind='tcp'): 
           d=str(connect.laddr[0])+' ' 
       conn.send(d) # prints ip 
           d=str(connect.laddr[1])+' ' 
       conn.send(d) # prints tcp ports      
        except psutil.AccessDenied: # won't show all the processes 
         pass 

        except psutil.NoSuchProcess: 
         pass 
      else: 
         continue 

     conn.send(" Enter the threshold...(in MB)(Press # at the end) ") 
     d="" 
     t=conn.recv(65536).decode('utf-8') 
     while(t!='#'): 
        d=d+str(t) 
        t=conn.recv(65536).decode('utf-8') 

       names=[]  # LIST OF PROCESSES TO BE KILLED... 
#A RECORD IS KEPT SO THAT THEY CAN BE RESTARTED...... 
       for p in psutil.pids(): 
        try: 
         p1=psutil.Process(p) 
         if(r in p1.name()): 
          if((p2[0]/(1024*1024))>=int(d)): 
           m=p1.name() 
           m=m.encode('ascii','ignore') # converting unicode object into string object 

           for l in o: 
            f=0 
            for root, dirs, files in os.walk(l): # walks through the entire file system of the Windows OS 
             #f=0 
             for name in files: 
              if name==m: 
               p1.kill() 
               conn.send("  Finally the process is killed...... ") 
               f=1 
               conn.send(str(os.path.abspath(os.path.join(root,name)))) 
               names.append(os.path.abspath(os.path.join(root,name))) 
               #pst=processThread(1,os.path.abspath(os.path.join(root,name))) 
               #pst.start() 
               #subprocess.Popen(str(os.path.abspath(os.path.join(root,name)))) 
               #if(p): 
               break 
             if(f==1): 
              break 

            if(f==1): 
             break 

        except psutil.AccessDenied: 
         pass 

        except psutil.NoSuchProcess: 
         pass 

        else: 
         continue 

     conn.send(" Now the processes will be restarted after the connection is terminated......") 
    conn.close() # closes the connection... 
     if(names): 
      for l in names: 
       subprocess.Popen(str(l)) 


class processThread(threading.Thread): # Thread class for Process Launch 
    def __init__(self,threadID,name): 
     threading.Thread.__init__(self) 
     self.threadID=threadID 
     self.name=name 

    def run(self): 
     subprocess.Popen(str(self.name)) 



class serverThread(threading.Thread): # Thread class for Server(FOR LISTENING) 
    def __init__(self, threadID, name,): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 
     self.name = name 

    def run(self): 
     threadLock.acquire() 
     host=raw_input("Enter the hostname.....") 
     HOST=socket.gethostbyname(host) 
     PORT=60000 # specific port available 
     s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     print 'Socket created' 
     #Bind socket to local host and port 
     try: 
      s.bind((HOST, PORT)) 
     except socket.error as msg: 
      print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] 
      sys.exit() 

     print 'Socket bind complete' 
     s.listen(10) # no of connections @ one time 
     print self.name+' now listening' 
     threadLock.release() 

     while 1: 
      conn, addr = s.accept() # connection gets established here.. 
      print 'Connected with ' + addr[0] + ':' + str(addr[1]) 
      conn.send('Thank you for connecting ') 
      # creates a new thread for the client services and processes the parameter and sends it back to the client 
      start_new_thread(proc_info,(conn,addr)) 

     s.close() 

threadLock=threading.Lock() 
thread1 =serverThread(1,"Server 1") 
thread1.start() # starting the server thread... 

請解釋這個問題的原因及解決方法(如果有的話)。

+0

刪除儘可能多的代碼,你可以仍然表現出這個問題。 –

回答

0

我對併發編程非常感興趣,但是閱讀代碼我知道該進程只能被殺死一次,並且只發生在一個客戶端上。因此,如果沒有鏈接到此連接的進程正在運行,則應引入額外的檢查以關閉連接。

+0

爲什麼另一個線程會死? – rahuljain1313

相關問題