2
# Copyright 2013 Canonical Ltd.
4
# Sylvain Pineau <sylvain.pineau@canonical.com>
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License version 3,
8
# as published by the Free Software Foundation.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
Script checking gpu lockups.
21
Several threads are started to exercise the GPU in ways that can cause gpu
23
Inspired by the workload directory of the xdiagnose package.
31
from gi.repository import Gio
32
from math import cos, sin
33
from threading import Thread
36
class GlxThread(Thread):
38
Start a thread running glxgears
44
self.process = subprocess.Popen(
45
["glxgears","-geometry", "400x400"],
46
stdout=subprocess.PIPE,
47
stderr=subprocess.STDOUT)
48
self.process.communicate()
49
except (subprocess.CalledProcessError, FileNotFoundError) as er:
50
print("WARNING: Unable to start glxgears (%s)" % er)
54
if not hasattr(self, 'id'):
55
print("WARNING: Attempted to terminate non-existing window.")
56
if hasattr(self, 'process'):
57
self.process.terminate()
60
class RotateGlxThread(Thread):
62
Start a thread performing glxgears windows rotations
65
def __init__(self, id, offset):
74
x = int(200 * self.offset + 100 * sin(j * 0.2))
75
y = int(200 * self.offset + 100 * cos(j * 0.2))
76
coords = "%s,%s" % (x, y)
78
'wmctrl -i -r %s -e 0,%s,-1,-1' % (self.id, coords),
81
time.sleep(0.002 * self.offset)
86
class ChangeWorkspace(Thread):
88
Start a thread performing fast workspace switches
91
def __init__(self, hsize, vsize, xsize, ysize):
101
for i in range(self.hsize):
102
for j in range(self.vsize):
104
'wmctrl -o %s,%s' % (self.xsize * j, self.ysize * i),
108
# Switch back to workspace #1
109
subprocess.call('wmctrl -o 0,0', shell=True)
113
class Html5VideoThread(Thread):
115
Start a thread performing playback of an HTML5 video in firefox
119
def html5_path(self):
120
if os.getenv('CHECKBOX_SHARE'):
122
os.getenv('CHECKBOX_SHARE'),
123
'data/websites/html5_video.html')
126
if self.html5_path and os.path.isfile(self.html5_path):
128
'firefox %s' % self.html5_path,
129
stdout=open(os.devnull, 'w'),
130
stderr=subprocess.STDOUT,
133
print("WARNING: unable to start html5 video playback.")
134
print("WARNING: test results may be invalid.")
137
if self.html5_path and os.path.isfile(self.html5_path):
138
subprocess.call("pkill firefox", shell=True)
141
def check_gpu(log=None):
143
log = '/var/log/kern.log'
144
with open(log, 'rb') as f:
145
if re.findall(r'gpu\s+hung', str(f.read()), flags=re.I):
146
print("GPU hung Detected")
155
subprocess.call("pkill 'glxgears|firefox'", shell=True)
157
Html5Video = Html5VideoThread()
160
source = Gio.SettingsSchemaSource.get_default()
163
GlxWindows.append(GlxThread())
164
GlxWindows[i].start()
167
windows = subprocess.check_output(
168
'wmctrl -l | grep glxgears',
170
except subprocess.CalledProcessError as er:
171
print("WARNING: Got an exception %s" % er)
173
for app in sorted(windows.splitlines(), reverse=True):
174
if not b'glxgears' in app:
176
GlxWindows[i].id = str(
177
re.match(b'^(0x\w+)', app).group(0), 'utf-8')
179
if hasattr(GlxWindows[i], "id"):
180
rotator = RotateGlxThread(GlxWindows[i].id, i + 1)
181
GlxRotate.append(rotator)
184
print("WARNING: Window {} not found, not rotating it.".format(i))
187
hsize_ori = vsize_ori = None
188
if source.lookup("org.compiz.core", True):
189
settings = Gio.Settings(
191
"/org/compiz/profiles/unity/plugins/core/"
193
hsize_ori = settings.get_int("hsize")
194
vsize_ori = settings.get_int("vsize")
195
settings.set_int("hsize", hsize)
196
settings.set_int("vsize", vsize)
199
hsize = int(subprocess.check_output(
200
'gconftool --get /apps/compiz-1/general/screen0/options/hsize',
202
vsize = int(subprocess.check_output(
203
'gconftool --get /apps/compiz-1/general/screen0/options/vsize',
205
(x_res, y_res) = re.search(
206
b'DG:\s+(\d+)x(\d+)',
207
subprocess.check_output('wmctrl -d', shell=True)).groups()
208
DesktopSwitch = ChangeWorkspace(
209
hsize, vsize, int(x_res) // hsize, int(y_res) // vsize)
210
DesktopSwitch.start()
214
for i in range(len(GlxRotate)):
215
GlxRotate[i].cancel = True
216
for i in range(len(GlxWindows)):
217
GlxWindows[i].terminate()
218
DesktopSwitch.cancel = True
220
Html5Video.terminate()
221
if check_gpu() or not Html5Video.html5_path:
224
if source.lookup("org.compiz.core", True):
225
settings = Gio.Settings(
227
"/org/compiz/profiles/unity/plugins/core/")
228
settings.set_int("hsize", hsize_ori)
229
settings.set_int("vsize", vsize_ori)
232
if __name__ == '__main__':