前面讲到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)
原文地址:https://www.cnblogs.com/shortnil/p/9866808.html
时间: 2024-11-05 18:27:15