-
Notifications
You must be signed in to change notification settings - Fork 0
/
start.py
executable file
·267 lines (235 loc) · 9.81 KB
/
start.py
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#===============================================================================
# Written by Rentouch 2012 - http://www.rentouch.ch
#===============================================================================
#standard
import subprocess
import os
from threading import Thread
import time
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
import gtk
import signal
import logging
gtk.gdk.threads_init()
'''
Start
=====
In this file all which is done is launching and closing different elements of PB.
What do I need?
~~~~~~~~~~~~~~~
- Kivy branch core-x11 (transparent windows)
--> clone from: https://github.com/jegger/kivy.git;
---> install: sudo WITH_X11=1 python setup.py install
- wmiface
What does this script
~~~~~~~~~~~~~~~~~~~~~
This script launches all the PB - elements. In case of a shutdown or reboot it
will close them also. If any of the PB elements will crash, the script will
restart them immediately.
Why doesn't do this the controller?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is just a matter of stability.
In case of a controller crash all the progs will crash also.
But the PBase, PBSwitch and PBUpdater are running safely.
Because the controller is a complex structure, the possibility is bigger for a
crash of the controller than this simple start script.
How can I close or shutdown/reboot?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You have to call the function shutdown(reboot) over DBUS.
You can reach it under: session bus: org.PB.start (/start)
'''
#initialize logger
log = logging.getLogger('Start')
log.setLevel(logging.INFO)
hdlr = logging.FileHandler('data/logs/log.log')
consoleHandler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s [%(levelname)-8s] %(module)s%(lineno)-3s %(message)s")
hdlr.setFormatter(formatter)
consoleHandler.setFormatter(formatter)
log.addHandler(hdlr)
log.addHandler(consoleHandler)
log.info("*-----------Start(Controller) started-----------*")
class Start():
PBUpdater=True
PBase=True
PBSwitch=True
PID_PBUpdater=None
#list with all the scripts
script_list=[{"path":"../PBUpdater", "filename":"main.py", "PID":None, "run":True, "port":None},
{"path":"../PBController", "filename":"main.py", "PID":None, "run":True, "port":None},
{"path":"../PBase", "filename":"main.py", "PID":None, "run":True, "port":3335},
{"path":"../PBController", "filename":"switch.py", "PID":None, "run":True, "port":3334}]
def _launch(self, path, filename, index):
'''This is the function that actually launches any of the scripts.
While launching it stores the PID (for killing the process later)
int the list. This function is always a thread.
'''
#create watchdog to watch over the loop. If the loop gets executed more
#then three times in a row in less then 5seconds - close PBase suite
watchdog_start_time=time.time()
counter=0
#start the python script. In case of a crash start again until script_list<item>.run=False
while self.script_list[index]["run"]:
os.chdir(path)
if self.script_list[index]["port"]!=None:
if self.script_list[index]["filename"]=="switch.py":
#for the PBSwitch
os.environ['KIVY_WINDOW'] = 'x11'
pr=subprocess.Popen(["python", filename, "-p", "test:tuio,0.0.0.0:"+str(self.script_list[index]["port"])], env=os.environ, stdout=subprocess.PIPE,
preexec_fn=os.setsid)
os.environ.pop('KIVY_WINDOW')
else:
#for PBase
pr=subprocess.Popen(("python",filename, "-k","-p", "test:tuio,0.0.0.0:"+str(self.script_list[index]["port"])))
else:
pr=subprocess.Popen(("python",filename))
#fetch PID fpr process
self.script_list[index]["PID"]=pr.pid
log.info("Started process: "+str(self.script_list[index]["path"])+str(self.script_list[index]["filename"])+str(self.script_list[index]["PID"]))
start_time=time.time()
#special window operations
if self.script_list[index]["filename"]=="switch.py":
#for switch (above)
while time.time()-start_time<10 and self.script_list[index]["run"]:
if self.modify_window(self.script_list[index]["PID"], True, "keepAbove"):
break
time.sleep(3)
elif self.script_list[index]["filename"]=="main.py" and self.script_list[index]["path"]=="../PBase":
#for pbase
while time.time()-start_time<10 and self.script_list[index]["run"]:
if self.modify_window(self.script_list[index]["PID"], True, "keepBelow"):
break
time.sleep(2)
#wait (make synchronous) here until the script breaks somehow
pr.wait()
#set PID to False, because the process isn't running anymore
self.script_list[index]["PID"]=False
#watchdog count up and check
counter+=1
if counter>=3:
if time.time()-watchdog_start_time<=10:
self.stop()
break
else:
counter=0
watchdog_start_time=time.time()
def modify_window(self, pid, everydesktop, args):
'''This functions modifies the window if wmctrl exists
:param pid: the pid of the window
:param everydesktop: bool: if window should appear on every desktop
:param args: the args for adding in wmctrl: above or below
'''
if not self.wmiface:
return False
#get window id
proc = subprocess.Popen('wmiface findNormalWindows "" "" "" "" '+str(pid)+' false', shell=True, stdout=subprocess.PIPE)
proc.wait()
window_id=None
for line in proc.stdout:
window_id=line.replace("\n", "")
if window_id==None:
log.info("Can't find window with PID:"+str(pid))
return False
#modify window with args
command='wmiface '+args+' '+window_id+' True'
pr=subprocess.Popen(command, shell=True)
pr.wait()
#modify window with desktop
if not everydesktop:
return True
command='wmiface setWindowDesktop '+window_id+' -1'
pr=subprocess.Popen(command, shell=True)
pr.wait()
return True
def cmd_exists(self, cmd):
'''checks if this command exists
'''
if len(os.popen(cmd).readlines())==0:
return False
else:
return True
def start(self):
'''This function makes a loop trough the list and makes a thread for
every script.
'''
#check for wmctrl
self.wmiface=self.cmd_exists("wmiface numberOfDesktops")
#start scripts
self.start_scripts()
def start_scripts(self):
'''This function starts all scripts
'''
log.info("Start all scripts")
#loop trough scripts
for index, script in enumerate(self.script_list):
script["run"]=True
t = Thread(target=self._launch, args=(script["path"], script["filename"], index))
t.start()
time.sleep(0.1)
def stop(self):
'''This function kills all the running scripts and closes the gtk main loop
'''
self.stop_scripts()
self.stop_gtk()
def stop_scripts(self):
'''This function kills all running scripts
'''
log.info("kill all scripts")
for script in self.script_list:
script["run"]=False
log.info("kill script: "+str(script["filename"])+str(script["PID"]))
if script["PID"]:
os.system("kill "+str(script["PID"]))
if script["filename"]=="switch.py":
os.killpg(script["PID"], signal.SIGTERM)
def stop_gtk(self):
'''This function stops the gtk mainloop and ends the life of this script
'''
log.info("Stop gtk main loop in start.py")
gtk.main_quit()
class DBusServer(dbus.service.Object):
'''DBus server from PBase.
Reachable under session bus: org.PB.start (/start)
'''
def __init__(self, start):
'''Initialize the session bus under: org.PB.start
:param start: start object
'''
self.start=start
bus_name = dbus.service.BusName('org.PB.start', bus=dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, '/start')
@dbus.service.method('org.PB.start')
def shutdown(self, reaction='stop'):
'''This function will shutdown the device or
restart in case the argument reboot is True
:param stop: reboot=>device reboot,
stop=>software stop,
shutdown=>device shutdown,
restart=>pbase suite restart
'''
if reaction=='stop':
log.info("Stop software")
return self.start.stop()
elif reaction=='reboot':
log.info("Reboot device")
return self.start.stop()
elif reaction=='restart':
log.info("Software suite restart")
self.start.stop_scripts()
time.sleep(3)
self.start.start()
else:
log.info("Shutdown device")
return self.start.stop()
DBusGMainLoop(set_as_default=True)
st=Start()
myservice = DBusServer(st)
st.start()
try:
gtk.main()
except (KeyboardInterrupt, SystemExit):
os.system("killall python")
sys.exit()