码迷,mamicode.com
首页 > 其他好文 > 详细

yocto-sumo源码解析(九): ProcessServer.main

时间:2018-10-28 22:04:25      阅读:281      评论:0      收藏:0      [点我收藏+]

标签:sub   man   share   temp   初始化   stderr   client   分析   lock   

前面讲到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

标签:sub   man   share   temp   初始化   stderr   client   分析   lock   

原文地址:https://www.cnblogs.com/shortnil/p/9866808.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!