为什么两个线程访问一个资源会崩溃一个线程?

时间:2015-06-09 05:53:19

标签: python sockets operating-system mutex deadlock

我创建了一个客户端服务器程序(在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...

请解释问题的原因及其解决方案(如果有的话)。

1 个答案:

答案 0 :(得分:0)

我自己对并发编程很新,但是阅读代码我感觉这个过程只能被杀死一次而且只发生在一个客户端上。因此,如果没有链接到此连接的进程正在运行,则应引入额外的检查来关闭连接。