Skip to content

LLVM.ContextDispose and LLVM.DisposeMemoryBuffer cause System.ExecutionEngineException #234

@ds5678

Description

@ds5678

Example Code

static unsafe void Method(string name, ReadOnlySpan<byte> content)
{
	fixed (byte* ptr = content)
	{
		nint namePtr = Marshal.StringToHGlobalAnsi(name);
		LLVMMemoryBufferRef buffer = LLVM.CreateMemoryBufferWithMemoryRange((sbyte*)ptr, (nuint)content.Length, (sbyte*)namePtr, 1);
		try
		{
			LLVMContextRef context = LLVMContextRef.Create();
			try
			{
				LLVMModuleRef module = context.ParseIR(buffer);
				//Do stuff
			}
			finally
			{
				context.Dispose(); // This fails consistently.
			}
		}
		finally
		{
			LLVM.DisposeMemoryBuffer(buffer); // This fails randomly.
			Marshal.FreeHGlobal(namePtr);
		}
	}
}

Attempt to fix

I tried making native methods (#225) which catch exceptions. There was no change.

uint8_t llvmsharp_Context_DisposeSafe(LLVMContextRef context, char** out_error)
{
    try
    {
        LLVMContextDispose(context);
        if (out_error)
        {
            *out_error = nullptr;
        }
        return 1; // Success
    }
    catch (const std::exception& e)
    {
        if (out_error)
        {
            *out_error = _strdup(e.what());
        }
        return 0; // Failure
    }
    catch (...)
    {
        if (out_error)
        {
            *out_error = _strdup("Unknown error occurred while disposing context.");
        }
        return 0; // Failure
    }
}

uint8_t llvmsharp_MemoryBuffer_DisposeSafe(LLVMMemoryBufferRef buffer, char** out_error)
{
    try
    {
        LLVMDisposeMemoryBuffer(buffer);
        if (out_error)
        {
            *out_error = nullptr;
        }
        return 1; // Success
    }
    catch (const std::exception& e)
    {
        if (out_error)
        {
            *out_error = _strdup(e.what());
        }
        return 0; // Failure
    }
    catch (...)
    {
        if (out_error)
        {
            *out_error = _strdup("Unknown error occurred while disposing memory buffer.");
        }
        return 0; // Failure
    }
}

void llvmsharp_FreeString(char* str)
{
    free(str);
}

Workaround

Currently, I just accept the memory leak and ignore the problem.

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