Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit ae5a76c

Browse files
committed
build: Manage mspdbsrv instances during Win builds
Builds were stalling and timing out on Windows, and this appeared to be due to `mspdbsrv` instances hanging around after the build had been completed. Further investigation revealed a host of issues related to `mspdbsrv` process management. This patch updates the Windows buildbot build script to prevent as many of these issues as possible.
1 parent a151257 commit ae5a76c

File tree

2 files changed

+65
-6
lines changed

2 files changed

+65
-6
lines changed

buildbot.py

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
import shutil
3232
import tarfile
3333

34+
# LiveCode build configuration script
35+
import config
36+
3437
# The set of platforms for which this branch supports automated builds
3538
BUILDBOT_PLATFORMS = ('linux-x86', 'linux-x86_64', 'android-armv6', 'mac',
3639
'ios', 'win-x86', 'emscripten')
@@ -77,6 +80,9 @@ def get_buildtype():
7780
def get_build_edition():
7881
return os.environ.get('BUILD_EDITION', 'community')
7982

83+
def get_git_commit():
84+
return subprocess.check_output(['git','rev-parse','HEAD']).strip()
85+
8086
################################################################
8187
# Defer to buildbot.mk
8288
################################################################
@@ -91,7 +97,6 @@ def exec_buildbot_make(target):
9197
################################################################
9298

9399
def exec_configure(args):
94-
import config
95100
print('config.py ' + ' '.join(args))
96101
sys.exit(config.configure(args))
97102

@@ -118,15 +123,69 @@ def exec_make(target):
118123
print(' '.join(args))
119124
sys.exit(subprocess.call(args))
120125

126+
# mspdbsrv is the service used by Visual Studio to collect debug
127+
# data during compilation. One instance is shared by all C++
128+
# compiler instances and threads. It poses a unique challenge in
129+
# several ways:
130+
#
131+
# - If not running when the build job starts, the build job will
132+
# automatically spawn it as soon as it needs to emit debug symbols.
133+
# There's no way to prevent this from happening.
134+
#
135+
# - The build job _doesn't_ automatically clean it up when it finishes
136+
#
137+
# - By default, mspdbsrv inherits its parent process' file handles,
138+
# including (unfortunately) some log handles owned by Buildbot. This
139+
# can prevent Buildbot from detecting that the compile job is finished
140+
#
141+
# - If a compile job starts and detects an instance of mspdbsrv already
142+
# running, by default it will reuse it. So, if you have a compile
143+
# job A running, and start a second job B, job B will use job A's
144+
# instance of mspdbsrv. If you kill mspdbsrv when job A finishes,
145+
# job B will die horribly. To make matters worse, the version of
146+
# mspdbsrv should match the version of Visual Studio being used.
147+
#
148+
# This class works around these problems:
149+
#
150+
# - It sets the _MSPDBSRV_ENDPOINT_ to a value that's probably unique to
151+
# the build, to prevent other builds on the same machine from sharing
152+
# the same mspdbsrv endpoint
153+
#
154+
# - It launches mspdbsrv with _all_ file handles closed, so that it
155+
# can't block the build from being detected as finished.
156+
#
157+
# - It explicitly kills mspdbsrv after the build job has finished.
158+
#
159+
# - It wraps all of this into a context manager, so mspdbsrv gets killed
160+
# even if a Python exception causes a non-local exit.
161+
class UniqueMspdbsrv(object):
162+
def __enter__(self):
163+
os.environ['_MSPDBSRV_ENDPOINT_'] = '{}-{}-{}'.format(
164+
get_build_edition(), get_git_commit()[0:8], get_buildtype())
165+
166+
mspdbsrv_exe = os.path.join(config.get_program_files_x86(),
167+
'Microsoft Visual Studio 10.0\\Common7\\IDE\\mspdbsrv.exe')
168+
args = [mspdbsrv_exe, '-start', '-shutdowntime', '-1']
169+
print(' '.join(args))
170+
self.proc = subprocess.Popen(args, close_fds=True)
171+
return self
172+
173+
def __exit__(self, type, value, traceback):
174+
self.proc.terminate()
175+
return False
176+
121177
def exec_msbuild(platform):
122178
# Run the make.cmd batch script; it's run using Wine if this is
123179
# not actually a Windows system.
124180
cwd = 'build-' + platform
125181

126182
if _platform.system() == 'Windows':
127-
args = ['cmd', '/C', '..\\make.cmd']
128-
print(' '.join(args))
129-
sys.exit(subprocess.call(args, cwd=cwd))
183+
with UniqueMspdbsrv() as mspdbsrv:
184+
args = ['cmd', '/C', '..\\make.cmd']
185+
print(' '.join(args))
186+
result = subprocess.call(args, cwd=cwd)
187+
188+
sys.exit(result)
130189

131190
else:
132191
args = ['wine', 'cmd', '/K', '..\\make.cmd']

make.cmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ ECHO %ProgramFilesBase%
1818
@REM Run this with its CWD outside the build tree so that
1919
@REM the fact it hangs around does not interfere with
2020
@REM cleaning up the build tree.
21-
@pushd %ProgramFilesBase%
22-
@start /min /b mspdbsrv -start -spawn -shutdowntime -1
21+
@pushd \
22+
@REM @start /min mspdbsrv -start -spawn -shutdowntime -1
2323
@popd
2424

2525
@REM Select the correct build mode.

0 commit comments

Comments
 (0)