From 8eaa2be5d9f6b8cd19ee6c0bcd737b4ba3a0afc5 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 27 Oct 2021 10:19:42 -0400 Subject: [PATCH] Fix crash when getting cuda options We could have an OptionOverrideProxy of an OptionOverrideProxy, recursively. This fix is a minimal subset of the refactoring I did in https://github.com/mesonbuild/meson/pull/9394. Instead of faking UserOption we can just do a shallow copy of one and set a new value on it. Fixes: #9448 --- mesonbuild/mesonlib/universal.py | 19 +++++-------------- test cases/cuda/16 multistd/lib.cu | 3 +++ test cases/cuda/16 multistd/main.cu | 3 ++- test cases/cuda/16 multistd/meson.build | 8 +++++++- 4 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 test cases/cuda/16 multistd/lib.cu diff --git a/mesonbuild/mesonlib/universal.py b/mesonbuild/mesonlib/universal.py index 831cb2ae0..d93133e14 100644 --- a/mesonbuild/mesonlib/universal.py +++ b/mesonbuild/mesonlib/universal.py @@ -28,6 +28,7 @@ from tempfile import TemporaryDirectory import typing as T import uuid import textwrap +import copy from mesonbuild import mlog @@ -61,7 +62,6 @@ __all__ = [ 'OptionKey', 'dump_conf_header', 'OptionOverrideProxy', - 'OptionProxy', 'OptionType', 'OrderedSet', 'PerMachine', @@ -1918,16 +1918,6 @@ def run_once(func: T.Callable[..., _T]) -> T.Callable[..., _T]: return wrapper -class OptionProxy(T.Generic[_T]): - def __init__(self, value: _T, choices: T.Optional[T.List[str]] = None): - self.value = value - self.choices = choices - - def set_value(self, v: _T) -> None: - # XXX: should this be an error - self.value = v - - class OptionOverrideProxy(collections.abc.MutableMapping): '''Mimic an option list but transparently override selected option @@ -1943,15 +1933,16 @@ class OptionOverrideProxy(collections.abc.MutableMapping): for o in options: self.options.update(o) - def __getitem__(self, key: 'OptionKey') -> T.Union['UserOption', OptionProxy]: + def __getitem__(self, key: 'OptionKey') -> T.Union['UserOption']: if key in self.options: opt = self.options[key] if key in self.overrides: - return OptionProxy(opt.validate_value(self.overrides[key]), getattr(opt, 'choices', None)) + opt = copy.copy(opt) + opt.set_value(self.overrides[key]) return opt raise KeyError('Option not found', key) - def __setitem__(self, key: 'OptionKey', value: T.Union['UserOption', OptionProxy]) -> None: + def __setitem__(self, key: 'OptionKey', value: T.Union['UserOption']) -> None: self.overrides[key] = value.value def __delitem__(self, key: 'OptionKey') -> None: diff --git a/test cases/cuda/16 multistd/lib.cu b/test cases/cuda/16 multistd/lib.cu new file mode 100644 index 000000000..8b5d5a7ef --- /dev/null +++ b/test cases/cuda/16 multistd/lib.cu @@ -0,0 +1,3 @@ +int do_cuda_stuff() { + return 0; +} diff --git a/test cases/cuda/16 multistd/main.cu b/test cases/cuda/16 multistd/main.cu index a2ffba489..7b06570f8 100644 --- a/test cases/cuda/16 multistd/main.cu +++ b/test cases/cuda/16 multistd/main.cu @@ -7,6 +7,7 @@ auto cuda_devices(void) { return result; } +int do_cuda_stuff(); int main(void) { int n = cuda_devices(); @@ -16,5 +17,5 @@ int main(void) { } std::cout << "Found " << n << "Cuda devices.\n"; - return 0; + return do_cuda_stuff(); } diff --git a/test cases/cuda/16 multistd/meson.build b/test cases/cuda/16 multistd/meson.build index 47f062901..36709d85c 100644 --- a/test cases/cuda/16 multistd/meson.build +++ b/test cases/cuda/16 multistd/meson.build @@ -2,6 +2,12 @@ project('C++-CUDA multi-std', 'cpp', 'cuda', version : '1.0.0', default_options : ['cpp_std=c++17', 'cuda_std=c++14']) -exe = executable('prog', 'main.cu') +# Regression test: Passing override_options used to cause a crash. +# See https://github.com/mesonbuild/meson/issues/9448. +libcpp11 = static_library('testcpp11', 'lib.cu', + override_options: ['cpp_std=c++11'] +) + +exe = executable('prog', 'main.cu', link_with: libcpp11) # The runtimes leak memory, so ignore it. test('cudatest', exe, env: ['ASAN_OPTIONS=detect_leaks=0'])