Bug 148857 - Handle is not initialized exception when bootstrapping with .Net (but not in .Net Framework)
Summary: Handle is not initialized exception when bootstrapping with .Net (but not in ...
Status: NEW
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: sdk (show other bugs)
Version:
(earliest affected)
7.3.1.3 release
Hardware: x86-64 (AMD64) Windows (All)
: medium normal
Assignee: Not Assigned
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: .NET
  Show dependency treegraph
 
Reported: 2022-04-29 16:27 UTC by Michele Locati
Modified: 2024-01-13 20:31 UTC (History)
7 users (show)

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michele Locati 2022-04-29 16:27:20 UTC
Description:
Bootstrapping in .Net (tested with .Net 6) fails, whereas bootstrapping in .Net Framework (tested with .Net Framework 4.8) succeeds.


Consider this C# code:


static int Main()
{
    string programPath = GetProgramPath();

    System.Environment.SetEnvironmentVariable(
        "UNO_PATH",
        programPath,
        System.EnvironmentVariableTarget.Process
    );
    System.Environment.SetEnvironmentVariable(
        "URE_BOOTSTRAP",
        $"vnd.sun.star.pathname:{System.IO.Path.Combine(programPath, "fundamental.ini")}",
        System.EnvironmentVariableTarget.Process
    );
    System.Environment.SetEnvironmentVariable(
        "PATH",
        $"{programPath}{System.IO.Path.PathSeparator}{System.Environment.GetEnvironmentVariable("PATH")}",
        System.EnvironmentVariableTarget.Process
    );
    try
    {
        uno.util.Bootstrap.defaultBootstrap_InitialComponentContext();
        System.Console.Out.WriteLine("OK!");
        return 0;
    }
    catch (System.Exception x)
    {
        System.Console.Error.WriteLine(x.GetType().FullName);
        System.Console.Error.WriteLine(x.Message);
        System.Console.Error.WriteLine(x.StackTrace);
        return 1;
    }
}
static string GetProgramPath()
{
    var programPath = Microsoft.Win32.Registry.GetValue(
        Microsoft.Win32.Registry.LocalMachine.Name + @"\SOFTWARE\LibreOffice\UNO\InstallPath",
        "",
        null
    ) as string;
    if (string.IsNullOrEmpty(programPath))
    {
        throw new System.Exception("Failed to detect the program path");
    }
    return programPath;
}


When executed with .Net Framework 4.8 everything works just fine.

When executed with .Net 6 we have:

System.InvalidOperationException
Handle is not initialized.
   at System.Runtime.InteropServices.GCHandle.FromIntPtr(IntPtr value)
   at uno.util.to_cli<class com::sun::star::uno::XComponentContext>(Reference<com::sun::star::uno::XComponentContext>* x)
   at uno.util.Bootstrap.defaultBootstrap_InitialComponentContext(String ini_file, IDictionaryEnumerator bootstrap_parameters)
   at uno.util.Bootstrap.defaultBootstrap_InitialComponentContext()
   at ConsoleDotNetFramework.Program.Main() in Program.cs:line 26


I tested it with LibreOffice 7.3.1.3 and with a fresh built of master (as of 2022-03-28): same results.
I also tested it in a Windows Sandbox: same results.



Steps to Reproduce:
1. Create a .Net (not .Net Framework) project
2. Add references to the DLLs that come with the SDK
3. Call uno.util.Bootstrap.defaultBootstrap_InitialComponentContext();

Actual Results:
defaultBootstrap_InitialComponentContext throws a System.InvalidOperationException exception:

Message: Handle is not initialized.
Stack trace:
   at System.Runtime.InteropServices.GCHandle.FromIntPtr(IntPtr value)
   at uno.util.to_cli<class com::sun::star::uno::XComponentContext>(Reference<com::sun::star::uno::XComponentContext>* x)
   at uno.util.Bootstrap.defaultBootstrap_InitialComponentContext(String ini_file, IDictionaryEnumerator bootstrap_parameters)
   at uno.util.Bootstrap.defaultBootstrap_InitialComponentContext()


Expected Results:
defaultBootstrap_InitialComponentContext should return a unoidl.com.sun.star.uno.XComponentContext instance without throwing an exception.


Reproducible: Always


User Profile Reset: Yes



Additional Info:
I published a simple Visual Studio solution to showcase this: see https://github.com/mlocati/libreoffice-uno-dotnet

The .Net project fails, the .NetFramework project succeeds (with exactly the same code)
Comment 1 Vitaly 2022-11-13 11:09:18 UTC
Does anyone fixing this error or can say something about it?
Comment 2 Mike Kaganski 2023-05-30 07:41:55 UTC
I repro the problem both with net6, and netcoreapp3.1, using x64 platform. Also the same is I use 'uno.util.Bootstrap.bootstrap()' instead of 'uno.util.Bootstrap.defaultBootstrap_InitialComponentContext()'.

If you enable the mixed-mode debugging (allowing to debug native code), and put breakpoint to mediate_mapInterface (cppu/source/uno/lbmap.cxx), then the problem happens in the call to

        (*pUno2To->mapInterface)( pUno2To, ppOut, pUnoI, pInterfaceTypeDescr );

where VS reports that mapInterface points to {cli_uno.dll!Mapping_uno2cli}, but you can't step into it from the code editor, and when you use disassembly to step into, it looks like a no-op, instead of the expected Mapping_uno2cli from cli_ure/source/uno_bridge/cli_bridge.cxx. Trying to put breakpoints in the latter function (or anywhere in the file) is impossible (the debugger tells that "No executable code of the debugger's target code type is associated with this line ...").

Since the actually called code is a no-op, the ppOut will still contain a nullptr upon returning to mediate_mapInterface, and then the "Handle is not initialized" happens.

And here I get stuck, having no experience with all this machinery. Stephan, do you have an idea?
Comment 3 truer0man 2023-10-02 17:17:31 UTC
Bug is still exist in 7.6.2.1 version of SDK. I'm using .NET 7.
Comment 4 eins99 2024-01-12 13:39:16 UTC
I confirm this bug for

Version: 7.6.4.1 (X86_64) / LibreOffice Community
Build ID: e19e193f88cd6c0525a17fb7a176ed8e6a3e2aa1
CPU threads: 2; OS: Windows 10.0 Build 22621; UI render: Skia/Raster; VCL: win
Locale: de-DE (de_DE); UI: de-DE
Calc: threaded

Since the bug is not yet assigned to anybody since one and a half year it seems that the issue is not with high priority.
 
My question is if there is a workaround?
Comment 5 Mike Kaganski 2024-01-13 17:23:05 UTC
https://learn.microsoft.com/en-us/dotnet/core/porting/cpp-cli

It seems to me, that the preferrable way to move forward would be to re-implement the cli assemblies in LibreOffice in C# or other language that doesn't have these limitations (if it is possible). Or to have a separate set of assemblies for .NET, as we have for .NET Framework.
Comment 6 Mike Kaganski 2024-01-13 17:32:03 UTC
FTR: running the DotNet6 config from the solution from comment 0, putting a breakpoint to loadEnv (cppu/source/uno/lbenv.cxx), when it gets called for "cli_uno", in the call to (*fpInit)( pEnv ), it will load the cli_uno.dll, which will load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll (seen in VS debugger's Output window); shortly after, an exception is thrown (no idea if it's important); and then, some assemblies for 4.0 will load, then unload; and finally, cli_uno.dll will unload. Neither before, nor after, it will be impossible to put a breakpoint to uno_initEnvironment in cli_ure/source/uno_bridge/cli_bridge.cxx.

When debugging DotNetFramework4.8 config, the uno_initEnvironment in cli_bridge.cxx will even be called directly, not from loadEnv.
Comment 7 eins99 2024-01-13 20:31:13 UTC
Since .NET Framework and .NET Core are now merged to .NET and will not see new development anymore, it would make sense to take in consideration to go this way also with LO. Otherwise coming releases of LO will not work with .NET.

How to deal with backward compatibility is another question.