yocto-sumo源碼解析(九): ProcessServer.main
阿新 • • 發佈:2018-10-28
running acc error: top delay 域套接字 err ror 列表
前面講到BitbakeServer實際上是一個ProcessServer,因此對ProcessServer進行了一個大略的分析集,這裏著重再介紹一下ProcessServer.main。
1. 初始化
def main(self): self.cooker.pre_serve() #調用cooker.pre_serve(),進入服務前的一些動作,這個後面繼續分解 bb.utils.set_process_name("Cooker") #設置本進程名稱為“Cooker” ready = [] #聲明一個列表,這個列表從後文看列應該是一個套接字描述符列表 self.controllersock = False #聲明本服務為非控制器套接字 fds = [self.sock] #將本服務套接字添加進文件描述符列表fds if self.xmlrpc: fds.append(self.xmlrpc) #若支持xmlrpc,那麽將xmlrpc同樣放入文件描述符列表 print("Entering server connection loop") #即將進入服務器連接循環 def disconnect_client(self, fds): #定義一個斷開客戶連接的函數,後面會要用到 if not self.haveui: return print("Disconnecting Client") fds.remove(self.controllersock) #從文件描述符列表中刪除控制器套接字描述符 fds.remove(self.command_channel) #從文件描述符列表中刪除命令通道套接字描述符,從這兩處並列的刪除步驟看,服務器接受兩個套接字 bb.event.unregister_UIHhandler(self.event_handle, True) #從事件處理器中刪除本事件處理器 self.command_channel_reply.writer.close() #關閉命令通道寫端 self.event_writer.writer.close() #關閉事件寫端 del self.event_writer #析構事件作者 self.controllersock.close() #控制器套接字關閉 self.controllersock = False self.haveui = False self.lastui = time.time() self.cooker.clientComplete() #調用cooker.clientComplete函數,後面再進行分解 if self.timeout is None: print("No timeout, exiting.") self.quit = True
2. 服務器連接循環
while not self.quit: if self.sock in ready: #假設本套接字在ready列表,那麽從本套接字接受一個控制器套接字連入,初始本套接字並不在ready列表 self.controllersock, address = self.sock.accept() if self.haveui: print("Dropping connection attempt as we have a UI %s" % (str(ready))) self.controllersock.close() else: print("Accepting %s" % (str(ready))) fds.append(self.controllersock) #將控制器套接字添加到文件描述符列表 if self.controllersock in ready: #若控制器套接字就緒,則從控制器套接字接受新的ui文件描述符 try: print("Connecting Client") ui_fds = recvfds(self.controllersock, 3) #根據控制器套接字中取3個套接字,分別用於事件作者,命令通道作者,命令通道讀者 # Where to write events to writer = ConnectionWriter(ui_fds[0]) #新建連接作者,用於事件處理 self.event_handle = bb.event.register_UIHhandler(writer, True) #新建本事件處理器 self.event_writer = writer # Where to read commands from reader = ConnectionReader(ui_fds[1]) #新建連接命令通道讀者 fds.append(reader) #將讀者添加進文件描述符列表 self.command_channel = reader # Where to send command return values to writer = ConnectionWriter(ui_fds[2]) #新建連接命令通道作者,用於向客戶發出回應 self.command_channel_reply = writer self.haveui = True except (EOFError, OSError): disconnect_client(self, fds) #出現異常則斷開客戶連接 if not self.timeout == -1.0 and not self.haveui and self.lastui and self.timeout and (self.lastui + self.timeout) < time.time(): print("Server timeout, exiting.") self.quit = True if self.command_channel in ready: #命令通道就緒,從命令通道中讀取一條命令 try: command = self.command_channel.get() except EOFError: # Client connection shutting down ready = [] disconnect_client(self, fds) #出現異常則斷開客戶連接 continue if command[0] == "terminateServer": self.quit = True continue try:個 print("Running command %s" % command) self.command_channel_reply.send(self.cooker.command.runCommand(command)) #執行接收到的命令並且構造響應
except Exception as e:
logger.exception(‘Exception in server main event loop running command %s (%s)‘ % (command, str(e)))
if self.xmlrpc in ready: #xmlrpc就緒,處理xmlrpc請求。
self.xmlrpc.handle_requests()
ready = self.idle_commands(.1, fds) #從套接字中獲取就緒的套接字
3. 退出清理
print("Exiting") # Remove the socket file so we don‘t get any more connections to avoid races os.unlink(self.sockname) #刪除域套接字文件 self.sock.close() #關閉本套接字,這裏順序上存疑 try: self.cooker.shutdown(True) #關閉cooker self.cooker.notifier.stop() #停止notify self.cooker.confignotifier.stop() #停止confignotify except: pass self.cooker.post_serve() #調用cooker.post_serve(),這個在後面進行分解 # Finally release the lockfile but warn about other processes holding it open lock = self.bitbake_lock lockfile = lock.name lock.close() #關閉bitbake_lock lock = None while not lock: with bb.utils.timeout(3): lock = bb.utils.lockfile(lockfile, shared=False, retry=False, block=True) if not lock: # Some systems may not have lsof available procs = None try: procs = subprocess.check_output(["lsof", ‘-w‘, lockfile], stderr=subprocess.STDOUT) except OSError as e: if e.errno != errno.ENOENT: raise if procs is None: # Fall back to fuser if lsof is unavailable try: procs = subprocess.check_output(["fuser", ‘-v‘, lockfile], stderr=subprocess.STDOUT) except OSError as e: if e.errno != errno.ENOENT: raise msg = "Delaying shutdown due to active processes which appear to be holding bitbake.lock" if procs: msg += ":\n%s" % str(procs) print(msg) return # We hold the lock so we can remove the file (hide stale pid data) bb.utils.remove(lockfile) bb.utils.unlockfile(lock)
yocto-sumo源碼解析(九): ProcessServer.main