1. 程式人生 > >yocto-sumo源碼解析(九): ProcessServer.main

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

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