📄 ipc.py
字号:
mutex.Detach() lasterror = win32api.GetLastError() if lasterror == winerror.ERROR_ALREADY_EXISTS: takeover = 0 try: # if the mutex already exists, discover which port to connect to. # if something goes wrong with that, tell us to take over the # role of master takeover = self.discover_sic_socket() except: pass if not takeover: raise BTFailure(_("Global mutex already created.")) self.master = 1 # lazy free port code port_limit = 50000 while self.port < port_limit: try: controlsocket = self.rawserver.create_serversocket(self.port, '127.0.0.1') self.controlsocket = controlsocket break except socket.error, e: self.port += 1 if self.port >= port_limit: raise BTFailure(_("Could not find an open port!")) filename = self._get_sic_path() (path, name) = os.path.split(filename) try: os.makedirs(path) except OSError, e: # 17 is dir exists if e.errno != 17: BTFailure(_("Could not create application data directory!")) f = open(filename, "w") f.write(str(self.port)) f.close() # we're done writing the control file, release the mutex so other instances can lock it and read the file # but don't destroy the handle until the application closes, so that the named mutex is still around win32event.ReleaseMutex(self.mutex) def discover_sic_socket(self): takeover = 0 # mutex exists and has been opened (not created, not locked). # wait for it so we can read the file r = win32event.WaitForSingleObject(self.mutex, win32event.INFINITE) # WAIT_OBJECT_0 means the mutex was obtained # WAIT_ABANDONED means the mutex was obtained, and it had previously been abandoned if (r != win32event.WAIT_OBJECT_0) and (r != win32event.WAIT_ABANDONED): raise BTFailure(_("Could not acquire global mutex lock for controlsocket file!")) filename = self._get_sic_path() try: f = open(filename, "r") self.port = int(f.read()) f.close() except: if r == win32event.WAIT_ABANDONED: ipc_logger.warning(_("A previous instance of BT was not cleaned up properly. Continuing.")) # take over the role of master takeover = 1 else: ipc_logger.warning((_("Another instance of BT is running, but \"%s\" does not exist.\n") % filename)+ _("I'll guess at the port.")) try: self.port = CONTROL_SOCKET_PORT self.send_command('no-op') ipc_logger.warning(_("Port found: %d") % self.port) try: f = open(filename, "w") f.write(str(self.port)) f.close() except: traceback.print_exc() except: # this is where this system falls down. # There's another copy of BitTorrent running, or something locking the mutex, # but I can't communicate with it. ipc_logger.warning(_("Could not find port.")) # we're done reading the control file, release the mutex so other instances can lock it and read the file win32event.ReleaseMutex(self.mutex) return takeover #blocking version without rawserver def send_command(self, command, *datas): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect(('127.0.0.1', self.port)) s.send(tobinary(len(command))) s.send(command) for data in datas: data = data.encode('utf-8') s.send(tobinary(len(data))) s.send(data) s.close() except socket.error, e: try: s.close() except: pass raise BTFailure(_("Could not send command: ") + unicode(e.args[0])) def stop(self): if self.master: r = win32event.WaitForSingleObject(self.mutex, win32event.INFINITE) filename = self._get_sic_path() try: os.remove(filename) except OSError, e: # print, but continue traceback.print_exc() self.master = 0 win32event.ReleaseMutex(self.mutex) # close it so the named mutex goes away win32api.CloseHandle(self.mutex) self.mutex = Noneif os.name == 'nt': class HandlerObject(pywin.mfc.object.Object): def __init__(self, handler, target): self.handler = handler pywin.mfc.object.Object.__init__(self, target) class Topic(HandlerObject): def __init__(self, handler, target): target.AddItem(dde.CreateStringItem("")) HandlerObject.__init__(self, handler, target) def Request(self, x): # null byte hack x = x.replace("\\**0", "\0") items = x.split("|") self.handler(items[0], *items[1:]) return ("OK") # remote procedure call #def Exec(self, x): # exec x class Server(HandlerObject): def CreateSystemTopic(self): return Topic(self.handler, dde.CreateServerSystemTopic()) def Status(self, s): ipc_logger.debug(_("IPC Status: %s") % s) def stop(self): self.Shutdown() self.Destroy()class SingleInstanceMutex(object): def __init__(self): obtain_mutex = False self.mutex = win32event.CreateMutex(None, obtain_mutex, app_name) self.lasterror = win32api.GetLastError() def close(self): del self.mutex def IsAnotherInstanceRunning(self): return winerror.ERROR_ALREADY_EXISTS == self.lasterrorif os.name == 'nt': g_mutex = SingleInstanceMutex()class IPCWin32DDE(IPC): def create(self): self.server = None if g_mutex.IsAnotherInstanceRunning(): # test whether there is a program actually running that holds # the mutex. for i in xrange(10): # try to connect first self.client = Server(None, dde.CreateServer()) self.client.Create(app_name, dde.CBF_FAIL_SELFCONNECTIONS|dde.APPCMD_CLIENTONLY) self.conversation = dde.CreateConversation(self.client) try: self.conversation.ConnectTo(app_name, self.name) raise BTFailure("DDE Conversation connected.") except dde.error, e: # no one is listening pass # clean up self.client.stop() del self.client del self.conversation ipc_logger.warning("No DDE Server is listening, but the global mutex exists. Retry %d!" % i) time.sleep(1.0) # oh no you didn't! if i == 5: pykill.kill_process(app_name) # continuing might be dangerous (two instances) raise Exception("No DDE Server is listening, but the global mutex exists!") # start server self.server = Server(self.handle_command, dde.CreateServer()) self.server.Create(app_name, dde.CBF_FAIL_SELFCONNECTIONS|dde.APPCLASS_STANDARD) self.server.AddTopic(Topic(self.handle_command, dde.CreateTopic(self.name))) def send_command(self, command, *args): s = '|'.join([command, ] + list(args)) # null byte hack if s.count("\0") > 0: ipc_logger.warinig("IPC: String with null byte(s):" + s) s = s.replace("\0", "\\**0") s = s.encode('utf-8') result = self.conversation.Request(s) def stop(self): if self.server: server = self.server self.server = None server.stop()if os.name == 'nt': #ipc_interface = IPCWin32Socket ipc_interface = IPCWin32DDEelse: ipc_interface = IPCUnixSocket
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -