1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 import time
34 import socket
35 import random
36 import threading
37 import xmlrpclib
38
39 from python_qt_binding import QtCore
40 import rospy
41
43 '''
44 A class to retrieve the state of launch servers. To retrieve the state a new
45 thread will be created.
46 '''
47 launch_server_signal = QtCore.Signal(str, int, list)
48 '''
49 @ivar: launch_server_signal is a signal (serveruri, pid, nodes), which is emitted, if a info from
50 launch server was successful retrieved.
51 '''
52 error_signal = QtCore.Signal(str, str)
53 '''
54 @ivar: error_signal is a signal (serveruri, error message), which is emitted,
55 if an error while retrieving a launch server info was occurred.
56 '''
57
59 QtCore.QObject.__init__(self)
60 self.__updateThreads = {}
61 self.__requestedUpdates = {}
62 self._lock = threading.RLock()
63
65 print " Shutdown launch update threads..."
66 self.__requestedUpdates.clear()
67 for key, thread in self.__updateThreads.iteritems():
68 thread.join(3)
69 print " Launch update threads are off!"
70
72 '''
73 This method starts a thread to get the informations about the launch server by
74 the given RCP uri of the launch server. If all informations are
75 retrieved, a C{launch_server_signal} of this class will be emitted. If for given
76 serveruri a thread is already running, it will be inserted to the requested
77 updates. For the same serveruri only one requested update can be stored.
78 On update error the requested update will be ignored.
79 This method is thread safe.
80
81 @param serveruri: the URI of the remote launch server
82 @type serveruri: C{str}
83 @param delayed_exec: Delay the execution of the request for given seconds.
84 @type delayed_exec: C{float}
85 '''
86 with self._lock:
87 try:
88 if (self.__updateThreads.has_key(serveruri)):
89 self.__requestedUpdates[serveruri] = delayed_exec
90 else:
91 self.__create_update_thread(serveruri, delayed_exec)
92 except:
93 pass
94
98
100 self.error_signal.emit(serveruri, error)
101 self.__handle_requests(serveruri)
102
104 with self._lock:
105 try:
106 thread = self.__updateThreads.pop(serveruri)
107 del thread
108 delayed_exec = self.__requestedUpdates.pop(serveruri)
109 self.__create_update_thread(serveruri, delayed_exec)
110 except KeyError:
111
112
113 pass
114 except:
115 import traceback
116 print traceback.format_exc()
117
124
125
127 '''
128 A thread to retrieve the list of pid and nodes from launch server and publish
129 it by sending a QT signal.
130 '''
131 launch_server_signal = QtCore.Signal(str, int, list)
132 error_signal = QtCore.Signal(str, str)
133
134 - def __init__(self, launch_serveruri, delayed_exec=0.0, parent=None):
135 QtCore.QObject.__init__(self)
136 threading.Thread.__init__(self)
137 self._launch_serveruri = launch_serveruri
138 self._delayed_exec = delayed_exec
139 self.setDaemon(True)
140
142 '''
143 '''
144 try:
145 delay = self._delayed_exec+0.5+random.random()
146 time.sleep(delay)
147 socket.setdefaulttimeout(25)
148 server = xmlrpclib.ServerProxy(self._launch_serveruri)
149 code, msg, pid = server.get_pid()
150 code, msg, nodes = server.get_node_names()
151 self.launch_server_signal.emit(self._launch_serveruri, pid, nodes)
152 except:
153 import traceback
154
155 formatted_lines = traceback.format_exc().splitlines()
156 rospy.logwarn("Connection to launch server @ %s failed:\n\t%s", str(self._launch_serveruri), formatted_lines[-1])
157
158 self.error_signal.emit(self._launch_serveruri, formatted_lines[-1])
159 finally:
160 if not socket is None:
161 socket.setdefaulttimeout(None)
162