Merge lp:~sylvain-pineau/checkbox/story482.9_gpu_lockup into lp:checkbox

Proposed by Sylvain Pineau
Status: Merged
Merged at revision: 1310
Proposed branch: lp:~sylvain-pineau/checkbox/story482.9_gpu_lockup
Merge into: lp:checkbox
Diff against target: 247 lines (+220/-1)
3 files modified
debian/control (+1/-1)
jobs/graphics.txt.in (+21/-0)
scripts/gpu_test (+198/-0)
To merge this branch: bzr merge lp:~sylvain-pineau/checkbox/story482.9_gpu_lockup
Reviewer Review Type Date Requested Status
Marc Tardif (community) Approve
Review via email: mp+96442@code.launchpad.net

Description of the change

The goal here is to perform some challenging graphic workloads on the gpu and check logs for lockup.
Most of them are inspired by xdiagnose workloads.
To do so, I've created a threaded application that:
- start 2 glxgears and move the corresponding windows,
- change workspaces/viewports quickly,
- start a loop of flash playbacks in firefox,
- suspend/resume (S3) one time for 30s

After 80 seconds, the script checks kern.log for the "gpu hung" pattern.

To post a comment you must log in.
Revision history for this message
Marc Tardif (cr3) wrote :

Looks good, very nice code! However, I will report a bug to avoid using os.environ["CHECKBOX_SHARE"], which also happens to appear in another script, so that it can be run more easily from the command line.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2012-03-02 14:18:04 +0000
3+++ debian/control 2012-03-07 19:46:24 +0000
4@@ -12,7 +12,7 @@
5 Architecture: any
6 Depends: ${misc:Depends}, ${python:Depends}, debconf, python-libxml2, udev
7 Recommends: dpkg (>= 1.13), gstreamer0.10-gconf, lsb-release, perl, pm-utils, python-apport, python-apt, python-dateutil, python-gst0.10, python-gtk2
8-Suggests: checkbox-cli | checkbox-gtk, bonnie++, bootchart, bzr, cvs, ethtool, flex, fwts, git-core, hdparm, lshw, make, nmap, obexd-client, python-pexpect, smartmontools, sox, stress, wodim
9+Suggests: checkbox-cli | checkbox-gtk, bonnie++, bootchart, bzr, cvs, ethtool, flex, fwts, git-core, hdparm, lshw, make, nmap, obexd-client, python-pexpect, smartmontools, sox, stress, wodim, mesa-utils, wmctrl
10 Description: System testing application
11 This project provides an extensible interface for system testing. The
12 results can then be sent to Launchpad.
13
14=== modified file 'jobs/graphics.txt.in'
15--- jobs/graphics.txt.in 2012-03-05 19:10:06 +0000
16+++ jobs/graphics.txt.in 2012-03-07 19:46:24 +0000
17@@ -147,6 +147,27 @@
18 2. Was the animation free from slowness/jerkiness?
19
20 plugin: shell
21+name: graphics/gpu_lockup
22+requires:
23+ package.name == 'firefox'
24+ package.name == 'fwts'
25+ package.name == 'wmctrl'
26+ package.name == 'mesa-utils'
27+depends: software/firefox-flash-video graphics/glxgears
28+user: root
29+command: gpu_test
30+_description:
31+ PURPOSE:
32+ Do some challenging operations and check for lockup on the GPU
33+ STEPS:
34+ 1. Create 2 glxgears windows and move them quickly
35+ 2. Switch workspaces/viewports with wmctrl
36+ 3. Launch a Flash playback in firefox
37+ 4. Suspend/resume
38+ VERIFICATION:
39+ 1. Atfer a 60s workload, check kern.log for reported GPU errors
40+
41+plugin: shell
42 name: graphics/screenshot
43 requires: package.name == 'fswebcam'
44 command: camera_test still --highest-device -f ${CHECKBOX_DATA}/screenshot.jpg -q 2>&1 | ansi_parser
45
46=== added file 'scripts/gpu_test'
47--- scripts/gpu_test 1970-01-01 00:00:00 +0000
48+++ scripts/gpu_test 2012-03-07 19:46:24 +0000
49@@ -0,0 +1,198 @@
50+#!/usr/bin/python
51+
52+import re
53+import os
54+import sys
55+import time
56+import pexpect
57+from subprocess import call, STDOUT
58+from threading import Thread
59+from tempfile import NamedTemporaryFile
60+from math import cos, sin
61+
62+
63+class GlxThread(Thread):
64+ """
65+ Start a thread running glxgears
66+ """
67+
68+ def run(self):
69+ pexpect.run('glxgears -geometry 400x400', timeout=None)
70+
71+ def terminate(self):
72+ call('wmctrl -i -c %s' %self.id, shell=True)
73+
74+
75+class RotateGlxThread(Thread):
76+ """
77+ Start a thread performing glxgears windows rotations
78+ """
79+
80+ def __init__(self, id, offset):
81+ Thread.__init__(self)
82+ self.id = id
83+ self.offset = offset
84+ self.cancel = False
85+
86+ def run(self):
87+ while(1):
88+ for j in range(60):
89+ x=int(200 * self.offset + 100 * sin(j * 0.2))
90+ y=int(200 * self.offset + 100 * cos(j * 0.2))
91+ coords="%s,%s" %(x, y)
92+ call('wmctrl -i -r %s -e 0,%s,-1,-1' %(self.id, coords),
93+ shell=True)
94+ time.sleep(0.002 * self.offset)
95+ if self.cancel:
96+ return
97+
98+
99+class ChangeWorkspace(Thread):
100+ """
101+ Start a thread performing fast workspace switches
102+ """
103+
104+ def __init__(self, size):
105+ Thread.__init__(self)
106+ self.size = size
107+ self.cancel = False
108+
109+ def run(self):
110+ while(1):
111+ for i in range(self.size):
112+ call('wmctrl -s %s' %i, shell=True)
113+ time.sleep(0.5)
114+ if self.cancel:
115+ # Switch back to workspace #1
116+ call('wmctrl -s 0', shell=True)
117+ return
118+
119+
120+class ChangeViewport(Thread):
121+ """
122+ Start a thread performing fast viewport switches
123+ """
124+
125+ def __init__(self, hsize, vsize, xsize, ysize):
126+ Thread.__init__(self)
127+ self.hsize = hsize
128+ self.vsize = vsize
129+ self.xsize = xsize
130+ self.ysize = ysize
131+ self.cancel = False
132+
133+ def run(self):
134+ while(1):
135+ for i in range(self.hsize):
136+ for j in range(self.vsize):
137+ call('wmctrl -o %s,%s' %(self.xsize * j, self.ysize * i),
138+ shell=True)
139+ time.sleep(0.5)
140+ if self.cancel:
141+ # Switch back to viewport #1
142+ call('wmctrl -o 0,0', shell=True)
143+ return
144+
145+
146+class FlashVideoThread(Thread):
147+ """
148+ Start a thread performing a Flash playback in firefox using totem
149+ """
150+
151+ def run(self):
152+ flv = os.environ['CHECKBOX_SHARE'] + '/data/websites/Flash_Video.flv'
153+ source = """
154+<html><head><meta http-equiv="refresh" content="5"></head><body>
155+<p>This page will reload and play this Flash video every 5s.</p>
156+<center><embed src="%s"></embed></center>
157+</body></html>""" %flv
158+
159+ with NamedTemporaryFile(suffix='.html', delete=False) as f:
160+ self.tempfile = f.name
161+ f.write("%s" %source)
162+ f.close()
163+ call('firefox %s' %f.name, stdout=open(os.devnull, 'w'),
164+ stderr=STDOUT, shell=True)
165+
166+ def terminate(self):
167+ call('wmctrl -c firefox', shell=True)
168+ os.unlink(self.tempfile)
169+
170+
171+def pidof(name):
172+ for pid in os.listdir("/proc"):
173+ if not pid.isdigit():
174+ continue
175+ try:
176+ exe = os.readlink(os.path.join("/proc", pid, "exe"))
177+ except OSError:
178+ continue
179+ if os.path.basename(exe) == name:
180+ return int(pid)
181+ return 0
182+
183+
184+def is_unity_2d_running():
185+ return pidof("unity-2d-panel") > 0
186+
187+
188+def check_gpu():
189+ f = open('/var/log/kern.log', 'r')
190+ with f:
191+ if re.findall(r'gpu\s+hung', f.read(), flags=re.I):
192+ print "GPU hung Detected"
193+ sys.exit(1)
194+
195+
196+def main():
197+ check_gpu()
198+ GlxWindows = []
199+ GlxRotate = []
200+ call("pkill 'glxgears|firefox'", shell=True)
201+
202+ FlashVideo = FlashVideoThread()
203+ FlashVideo.start()
204+
205+ for i in range(2):
206+ GlxWindows.append(GlxThread())
207+ GlxWindows[i].start()
208+ time.sleep(0.5)
209+ windows = pexpect.run('wmctrl -l | grep glxgears')
210+ for app in sorted(windows.splitlines(), reverse=True):
211+ if not 'glxgears' in app:
212+ continue
213+ GlxWindows[i].id = re.match(r'^(0x\w+)', app).group(0)
214+ break
215+ GlxRotate.append(RotateGlxThread(GlxWindows[i].id, i+1))
216+ GlxRotate[i].start()
217+
218+ if is_unity_2d_running():
219+ size = int(pexpect.run(
220+ 'gconftool --get /apps/metacity/general/num_workspaces'))
221+ DesktopSwitch = ChangeWorkspace(size)
222+ else:
223+ (x_res, y_res) = re.search(r'DG:\s+(\d+)x(\d+)',
224+ pexpect.run('wmctrl -d')).groups()
225+ hsize = int(pexpect.run(
226+ 'gconftool --get /apps/compiz-1/general/screen0/options/hsize'))
227+ vsize = int(pexpect.run(
228+ 'gconftool --get /apps/compiz-1/general/screen0/options/vsize'))
229+ DesktopSwitch = ChangeViewport(
230+ hsize, vsize, int(x_res) / hsize, int(y_res) / vsize)
231+ DesktopSwitch.start()
232+
233+ time.sleep(20)
234+ # Suspend/resume the SUT
235+ call('fwts -q s3 --s3-sleep-delay=30', shell=True)
236+ time.sleep(20)
237+
238+ for i in range(2):
239+ GlxRotate[i].cancel = True
240+ GlxWindows[i].terminate()
241+ DesktopSwitch.cancel = True
242+ time.sleep(10)
243+ FlashVideo.terminate()
244+ check_gpu()
245+
246+if __name__ == '__main__':
247+ sys.exit(main())

Subscribers

People subscribed via source and target branches