diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2018-11-28 19:38:16 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2018-11-28 19:48:44 +0530 |
commit | 2a82b100aa98576482569831317191f91cc39fb1 (patch) | |
tree | 8f071336e1b319d5cb229889ad51aca785490a5c | |
parent | d502e83493ea24e31c2b9e1034baf0a9408009ba (diff) | |
download | meson-nirbheek/fix-contextmanager-traceback.tar.gz |
compilers: Fix exception handling in compiler checksnirbheek/fix-contextmanager-traceback
Not yielding anything from a context manager because an exception was
raised causes the interpreter to output an undebuggable
'RuntimeError: generator didn't yield' exception.
Wrapping the entire compiler check in a `try: except: pass` is anyway
incorrect because we only want to ignore exceptions in cleaning up the
temporary directory, so reorganise the code and correctly ignore
exceptions only for that.
-rw-r--r-- | mesonbuild/compilers/compilers.py | 88 |
1 files changed, 45 insertions, 43 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 376143358..f4c3efbd3 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1070,55 +1070,57 @@ class Compiler: mlog.debug('Cached compiler stderr:\n', p.stde) yield p return + tmpdirname = tempfile.TemporaryDirectory() + if isinstance(code, str): + srcname = os.path.join(tmpdirname.name, + 'testfile.' + self.default_suffix) + with open(srcname, 'w') as ofile: + ofile.write(code) + elif isinstance(code, mesonlib.File): + srcname = code.fname + + # Construct the compiler command-line + commands = CompilerArgs(self) + commands.append(srcname) + commands += self.get_always_args() + if mode == 'compile': + commands += self.get_compile_only_args() + # Preprocess mode outputs to stdout, so no output args + if mode == 'preprocess': + commands += self.get_preprocess_only_args() + else: + output = self._get_compile_output(tmpdirname.name, mode) + commands += self.get_output_args(output) + # extra_args must be last because it could contain '/link' to + # pass args to VisualStudio's linker. In that case everything + # in the command line after '/link' is given to the linker. + commands += extra_args + # Generate full command-line with the exelist + commands = self.get_exelist() + commands.to_native() + mlog.debug('Running compile:') + mlog.debug('Working directory: ', tmpdirname.name) + mlog.debug('Command line: ', ' '.join(commands), '\n') + mlog.debug('Code:\n', code) + os_env = os.environ.copy() + os_env['LC_ALL'] = 'C' + p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname.name, env=os_env) + mlog.debug('Compiler stdout:\n', p.stdo) + mlog.debug('Compiler stderr:\n', p.stde) + p.commands = commands + p.input_name = srcname + if want_output: + p.output_name = output + else: + self.compiler_check_cache[key] = p try: - with tempfile.TemporaryDirectory() as tmpdirname: - if isinstance(code, str): - srcname = os.path.join(tmpdirname, - 'testfile.' + self.default_suffix) - with open(srcname, 'w') as ofile: - ofile.write(code) - elif isinstance(code, mesonlib.File): - srcname = code.fname - - # Construct the compiler command-line - commands = CompilerArgs(self) - commands.append(srcname) - commands += self.get_always_args() - if mode == 'compile': - commands += self.get_compile_only_args() - # Preprocess mode outputs to stdout, so no output args - if mode == 'preprocess': - commands += self.get_preprocess_only_args() - else: - output = self._get_compile_output(tmpdirname, mode) - commands += self.get_output_args(output) - # extra_args must be last because it could contain '/link' to - # pass args to VisualStudio's linker. In that case everything - # in the command line after '/link' is given to the linker. - commands += extra_args - # Generate full command-line with the exelist - commands = self.get_exelist() + commands.to_native() - mlog.debug('Running compile:') - mlog.debug('Working directory: ', tmpdirname) - mlog.debug('Command line: ', ' '.join(commands), '\n') - mlog.debug('Code:\n', code) - os_env = os.environ.copy() - os_env['LC_ALL'] = 'C' - p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname, env=os_env) - mlog.debug('Compiler stdout:\n', p.stdo) - mlog.debug('Compiler stderr:\n', p.stde) - p.commands = commands - p.input_name = srcname - if want_output: - p.output_name = output - else: - self.compiler_check_cache[key] = p - yield p + tmpdirname.cleanup() except (PermissionError, OSError): # On Windows antivirus programs and the like hold on to files so # they can't be deleted. There's not much to do in this case. Also, # catch OSError because the directory is then no longer empty. pass + finally: + yield p def get_colorout_args(self, colortype): return [] |