Skip to content

SIGSEGV on shutdown of tests #1830

Closed
Closed
@potterphx

Description

@potterphx

Environment

  • Pythonnet version: 3.0.0.a2
  • Python version: 3.10.4 (locally, 3.8 through 3.10 in GitHub actions)
  • Operating System: Ubuntu 22.04 (works find under Windows)
  • .NET Runtime:

Details

  • Describe what you were trying to get done.

    In several new projects, unit tests running fine under Windows, but when run under Ubuntu would would fail. On examining closer found that the unit tests all ran and passed, but there would be a SIGSEGV fault during shutdown. In chasing down possibly causes of the issue, the most common trigger appeared to a having a variable at the module level of .Net Type or of a Python container type which contained a .Net type.

  • What commands did you run to trigger this issue? If you can provide a
    Minimal, Complete, and Verifiable example
    this will help us understand the issue.

    Starting with one of the simpler projects, reducing it down a simple test case that reproduces the code.

    • src/acme
      • dlls/netstandard2.0
        • There were other DLLs from the results of a csproj build, but to reproduce this error only Microsoft.Extensions.Logging.Abstractions.dll is needed.
      • python_logger_working.py
        """Implementation of PythonLogger."""
        import logging
        import os
        import sys
        import clr  # type: ignore
        
        sys.path.append(os.path.join(os.path.dirname(__file__), "dlls/netstandard2.0"))
        clr.AddReference(r"Microsoft.Extensions.Logging.Abstractions")
        
        from Microsoft.Extensions.Logging import LogLevel  # type: ignore
        
        
        def get_python_level(log_level: LogLevel) -> int:
            """Get the equivalent python logging level for a .NET LogLevel."""
            python_level: int = logging.CRITICAL
            if log_level == getattr(LogLevel, "None"):
                python_level = logging.NOTSET
            elif log_level == LogLevel.Trace:
                # Python has no trace level, so we return the level right below debug as trace.
                python_level = logging.DEBUG - 1
            elif log_level == LogLevel.Debug:
                python_level = logging.DEBUG
            elif log_level == LogLevel.Information:
                python_level = logging.INFO
            elif log_level == LogLevel.Warning:
                python_level = logging.WARN
            elif log_level == LogLevel.Error:
                python_level = logging.ERROR
            return python_level
    • tests
      • test_python_logger.py
        import logging
        import pytest
        
        import clr
        from src.acme.python_logger_working import get_python_level
        
        clr.AddReference(r"Microsoft.Extensions.Logging.Abstractions")
        from Microsoft.Extensions.Logging import LogLevel
        
        
        @pytest.mark.parametrize(
            "dotnet_level,expected_level",
            [
                pytest.param(LogLevel.Critical, logging.CRITICAL),
                pytest.param(LogLevel.Error, logging.ERROR),
                pytest.param(LogLevel.Warning, logging.WARNING),
                pytest.param(LogLevel.Information, logging.INFO),
                pytest.param(LogLevel.Debug, logging.DEBUG),
                pytest.param(LogLevel.Trace, logging.DEBUG - 1)
            ]
        )
        def test_get_python_level(dotnet_level, expected_level) -> None:
            result = get_python_level(dotnet_level)
        
            # Verify
            assert( result == expected_level)
  • Workarounds and addition scenarios follow in comments.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions