| Home | Trees | Indices | Help |
|
|---|
|
|
1 """GNUmed scripting listener.
2
3 This module implements threaded listening for scripting.
4 """
5 #=====================================================================
6 __version__ = "$Revision: 1.7 $"
7 __author__ = "K.Hilbert <karsten.hilbert@gmx.net>"
8
9 import sys, time, threading, select, logging
10 import xmlrpc.server
11
12
13 _log = logging.getLogger('gm.scripting')
14
15 #=====================================================================
17
18 # FIXME: this should use /var/run/gnumed/xml-rpc-port.pid
19 # FIXME: and store the current port there
20
21 """This class handles how GNUmed listens for external requests.
22
23 It starts an XML-RPC server and forks a thread which
24 listens for incoming requests. Those requests are then
25 handed over to a macro executor and the results handed
26 back to the caller.
27 """
29 # listener thread will regularly try to acquire
30 # this lock, when it succeeds it will quit
31 self._quit_lock = threading.Lock()
32 if not self._quit_lock.acquire(0):
33 _log.error('cannot acquire thread quit lock !?! aborting')
34 import thread
35 raise thread.error("cannot acquire thread quit-lock")
36
37 # check for data every 'poll_interval' seconds
38 self._poll_interval = poll_interval
39 # localhost only for somewhat better security
40 self._listener_address = '127.0.0.1'
41 self._port = int(port)
42 self._macro_executor = macro_executor
43
44 self._server = xmlrpc.server.SimpleXMLRPCServer(addr=(self._listener_address, self._port), logRequests=False)
45 self._server.register_instance(self._macro_executor)
46 self._server.allow_reuse_address = True
47
48 self._thread = threading.Thread (
49 target = self._process_RPCs,
50 name = self.__class__.__name__
51 )
52 self._thread.setDaemon(True)
53 self._thread.start()
54
55 _log.info('scripting listener started on [%s:%s]' % (self._listener_address, self._port))
56 _log.info('macro executor: %s' % self._macro_executor)
57 _log.info('poll interval: %s seconds', self._poll_interval)
58 #-------------------------------
59 # public API
60 #-------------------------------
62 """Cleanly shut down. Complement to __init__()."""
63
64 if self._thread is None:
65 return
66
67 _log.info('stopping frontend scripting listener thread')
68 self._quit_lock.release()
69 try:
70 # give the worker thread time to terminate
71 self._thread.join(self._poll_interval+5)
72 try:
73 if self._thread.isAlive():
74 _log.error('listener thread still alive after join()')
75 _log.debug('active threads: %s' % threading.enumerate())
76 except:
77 pass
78 except:
79 print sys.exc_info()
80
81 self._thread = None
82
83 try:
84 self._server.socket.shutdown(2)
85 except:
86 _log.exception('cannot cleanly shutdown(5) scripting listener socket')
87
88 try:
89 self._server.socket.close()
90 except:
91 _log.exception('cannot cleanly close() scripting listener socket')
92 #-------------------------------
93 # internal helpers
94 #-------------------------------
96 """The actual thread code."""
97 while 1:
98 if self._quit_lock.acquire(0):
99 break
100 time.sleep(0.35) # give others time to acquire lock
101 if self._quit_lock.acquire(0):
102 break
103 # wait at most self.__poll_interval for new data
104 ready_input_sockets = select.select([self._server.socket], [], [], self._poll_interval)[0]
105 # any input available ?
106 if len(ready_input_sockets) != 0:
107 # we may be in __del__ so we might fail here
108 try:
109 self._server.handle_request()
110 except:
111 print("cannot serve RPC")
112 break
113 if self._quit_lock.acquire(0):
114 break
115 time.sleep(0.25)
116 if self._quit_lock.acquire(0):
117 break
118 else:
119 time.sleep(0.35)
120 if self._quit_lock.acquire(0):
121 break
122
123 # exit thread activity
124 return
125 #=====================================================================
126 # main
127 #=====================================================================
128 if __name__ == "__main__":
129
130 import xmlrpc.client
131
132 #-------------------------------
136 #-------------------------------
137 if (len(sys.argv) > 1) and (sys.argv[1] == 'test'):
138 import xmlrpclib
139
140 try:
141 listener = cScriptingListener(macro_executor=runner(), port=9999)
142 except:
143 _log.exception('cannot instantiate scripting listener')
144 sys.exit(1)
145
146 s = xmlrpclib.client.ServerProxy('http://localhost:9999')
147 try:
148 t = s.tell_time()
149 print t
150 except:
151 _log.exception('cannot interact with server')
152
153 listener.shutdown()
154
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Jan 25 02:55:27 2019 | http://epydoc.sourceforge.net |