blob: 7fc50c759aa6394d53b03590e1278e8414faa226 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
5# Copyright (C) 2006 - 2007 Richard Purdie
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
21"""
22Use this class to fork off a thread to recieve event callbacks from the bitbake
23server and queue them for the UI to process. This process must be used to avoid
24client/server deadlocks.
25"""
26
27import socket, threading, pickle
28from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
29
30class BBUIEventQueue:
31 def __init__(self, BBServer, clientinfo=("localhost, 0")):
32
33 self.eventQueue = []
34 self.eventQueueLock = threading.Lock()
35 self.eventQueueNotify = threading.Event()
36
37 self.BBServer = BBServer
38 self.clientinfo = clientinfo
39
40 server = UIXMLRPCServer(self.clientinfo)
41 self.host, self.port = server.socket.getsockname()
42
43 server.register_function( self.system_quit, "event.quit" )
44 server.register_function( self.send_event, "event.sendpickle" )
45 server.socket.settimeout(1)
46
47 self.EventHandler = None
48 count_tries = 0
49
50 # the event handler registration may fail here due to cooker being in invalid state
51 # this is a transient situation, and we should retry a couple of times before
52 # giving up
53
54 while self.EventHandler == None and count_tries < 5:
55 self.EventHandle = self.BBServer.registerEventHandler(self.host, self.port)
56
57 if (self.EventHandle != None):
58 break
59
60 bb.warn("Could not register UI event handler %s:%d, retry" % (self.host, self.port))
61 count_tries += 1
62 import time
63 time.sleep(1)
64
65
66 if self.EventHandle == None:
67 raise Exception("Could not register UI event handler")
68
69 self.server = server
70
71 self.t = threading.Thread()
72 self.t.setDaemon(True)
73 self.t.run = self.startCallbackHandler
74 self.t.start()
75
76 def getEvent(self):
77
78 self.eventQueueLock.acquire()
79
80 if len(self.eventQueue) == 0:
81 self.eventQueueLock.release()
82 return None
83
84 item = self.eventQueue.pop(0)
85
86 if len(self.eventQueue) == 0:
87 self.eventQueueNotify.clear()
88
89 self.eventQueueLock.release()
90 return item
91
92 def waitEvent(self, delay):
93 self.eventQueueNotify.wait(delay)
94 return self.getEvent()
95
96 def queue_event(self, event):
97 self.eventQueueLock.acquire()
98 self.eventQueue.append(event)
99 self.eventQueueNotify.set()
100 self.eventQueueLock.release()
101
102 def send_event(self, event):
103 self.queue_event(pickle.loads(event))
104
105 def startCallbackHandler(self):
106
107 self.server.timeout = 1
108 while not self.server.quit:
109 try:
110 self.server.handle_request()
111 except Exception as e:
112 import traceback
113 logger.error("BBUIEventQueue.startCallbackHandler: Exception while trying to handle request: %s\n%s" % (e, traceback.format_exc(e)))
114
115 self.server.server_close()
116
117 def system_quit( self ):
118 """
119 Shut down the callback thread
120 """
121 try:
122 self.BBServer.unregisterEventHandler(self.EventHandle)
123 except:
124 pass
125 self.server.quit = True
126
127class UIXMLRPCServer (SimpleXMLRPCServer):
128
129 def __init__( self, interface ):
130 self.quit = False
131 SimpleXMLRPCServer.__init__( self,
132 interface,
133 requestHandler=SimpleXMLRPCRequestHandler,
134 logRequests=False, allow_none=True)
135
136 def get_request(self):
137 while not self.quit:
138 try:
139 sock, addr = self.socket.accept()
140 sock.settimeout(1)
141 return (sock, addr)
142 except socket.timeout:
143 pass
144 return (None, None)
145
146 def close_request(self, request):
147 if request is None:
148 return
149 SimpleXMLRPCServer.close_request(self, request)
150
151 def process_request(self, request, client_address):
152 if request is None:
153 return
154 SimpleXMLRPCServer.process_request(self, request, client_address)
155