diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml index 0c308bd..c451f0f 100644 --- a/.github/workflows/ci-arm.yml +++ b/.github/workflows/ci-arm.yml @@ -1,9 +1,9 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - name: ARM64 Tests -on: [push, pull_request] +on: + push: + branches: master + pull_request: jobs: build: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45d1f06..f6f9e75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,9 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - name: Python Tests -on: [push, pull_request] +on: + push: + branches: master + pull_request: jobs: build: diff --git a/clr_loader/__init__.py b/clr_loader/__init__.py index d0d8ff2..4b08148 100644 --- a/clr_loader/__init__.py +++ b/clr_loader/__init__.py @@ -30,6 +30,9 @@ def get_mono( sgen: bool = True, debug: bool = False, jit_options: Optional[Sequence[str]] = None, + assembly_dir: Optional[str] = None, + config_dir: Optional[str] = None, + set_signal_chaining: bool = False ) -> Runtime: """Get a Mono runtime instance @@ -48,6 +51,20 @@ def get_mono( Whether to initialise Mono debugging :param jit_options: "Command line options" passed to Mono's ``mono_jit_parse_options`` + :param assembly_dir: + The base directory for assemblies, passed to ``mono_set_dirs`` + :param config_dir: + The base directory for configuration files, passed to ``mono_set_dirs`` + :param set_signal_chaining: + Whether to enable signal chaining, passed to ``mono_set_signal_chaining``. + If it is enabled, the runtime saves the original signal handlers before + installing its own, and calls the original ones in the following cases: + - SIGSEGV/SIGABRT while executing native code + - SIGPROF + - SIGFPE + - SIGQUIT + - SIGUSR2 + This currently only works on POSIX platforms """ from .mono import Mono @@ -62,6 +79,9 @@ def get_mono( config_file=_maybe_path(config_file), global_config_file=_maybe_path(global_config_file), libmono=libmono, + assembly_dir=assembly_dir, + config_dir=config_dir, + set_signal_chaining=set_signal_chaining, ) return impl diff --git a/clr_loader/ffi/mono.py b/clr_loader/ffi/mono.py index ed48cff..c194393 100644 --- a/clr_loader/ffi/mono.py +++ b/clr_loader/ffi/mono.py @@ -39,5 +39,10 @@ MonoObject* mono_runtime_invoke(MonoMethod *method, void *obj, void **params, MonoObject **exc); void* mono_object_unbox(MonoObject *object); + +void mono_set_dirs(const char *assembly_dir, const char* config_dir); + +void mono_set_signal_chaining(bool chain_signals); + """ ) diff --git a/clr_loader/mono.py b/clr_loader/mono.py index fb8ab1b..158ddb7 100644 --- a/clr_loader/mono.py +++ b/clr_loader/mono.py @@ -24,6 +24,9 @@ def __init__( jit_options: Optional[Sequence[str]] = None, config_file: Optional[Path] = None, global_config_file: Optional[Path] = None, + assembly_dir: Optional[str] = None, + config_dir: Optional[str] = None, + set_signal_chaining: bool = False, ): self._assemblies: Dict[Path, Any] = {} @@ -33,6 +36,9 @@ def __init__( jit_options=jit_options, global_config_file=optional_path_as_string(global_config_file), libmono=libmono, + assembly_dir=assembly_dir, + config_dir=config_dir, + set_signal_chaining=set_signal_chaining, ) if domain is None: @@ -121,11 +127,17 @@ def initialize( jit_options: Optional[Sequence[str]] = None, config_file: Optional[str] = None, global_config_file: Optional[str] = None, + assembly_dir: Optional[str] = None, + config_dir: Optional[str] = None, + set_signal_chaining: bool = False, ) -> str: global _MONO, _ROOT_DOMAIN if _MONO is None: _MONO = load_mono(libmono) + if assembly_dir is not None and config_dir is not None: + _MONO.mono_set_dirs(assembly_dir, config_dir) + # Load in global config (i.e /etc/mono/config) global_encoded = global_config_file or ffi.NULL _MONO.mono_config_parse(global_encoded) @@ -143,6 +155,9 @@ def initialize( else: options = [] + if set_signal_chaining: + _MONO.mono_set_signal_chaining(True) + if debug: _MONO.mono_debug_init(_MONO.MONO_DEBUG_FORMAT_MONO) diff --git a/clr_loader/util/find.py b/clr_loader/util/find.py index 22ba843..d5d7b89 100644 --- a/clr_loader/util/find.py +++ b/clr_loader/util/find.py @@ -1,5 +1,5 @@ import os -import os.path +import platform import shutil import sys from pathlib import Path @@ -42,7 +42,8 @@ def find_dotnet_root() -> Path: prog_files = Path(prog_files) dotnet_root = prog_files / "dotnet" elif sys.platform == "darwin": - if sys.maxsize > 2**32: # is_64bits + if "ARM64" in os.uname().version and platform.machine() == "x86_64": + # Apple Silicon in Rosetta 2 mode dotnet_root = Path("/usr/local/share/dotnet/x64") else: dotnet_root = Path("/usr/local/share/dotnet") diff --git a/tests/test_common.py b/tests/test_common.py index 1191102..f42020a 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -46,6 +46,21 @@ def test_mono_debug(example_netstandard): run_tests(asm) +def test_mono_signal_chaining(example_netstandard): + from clr_loader import get_mono + + mono = get_mono(set_signal_chaining=True) + asm = mono.get_assembly(example_netstandard / "example.dll") + + run_tests(asm) + +def test_mono_set_dir(example_netstandard): + from clr_loader import get_mono + + mono = get_mono(assembly_dir="/usr/lib", config_dir="/etc") + asm = mono.get_assembly(example_netstandard / "example.dll") + + run_tests(asm) def test_coreclr(example_netcore): from clr_loader import get_coreclr @@ -57,6 +72,17 @@ def test_coreclr(example_netcore): def test_coreclr_autogenerated_runtimeconfig(example_netstandard): + from multiprocessing import get_context + + p = get_context("spawn").Process( + target=_do_test_coreclr_autogenerated_runtimeconfig, args=(example_netstandard,) + ) + p.start() + p.join() + p.close() + + +def _do_test_coreclr_autogenerated_runtimeconfig(example_netstandard): from clr_loader import get_coreclr coreclr = get_coreclr()