Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot catch exceptions from reverse P/Invoke on Linux #7342

Closed
halter73 opened this issue Feb 2, 2017 · 5 comments
Closed

Cannot catch exceptions from reverse P/Invoke on Linux #7342

halter73 opened this issue Feb 2, 2017 · 5 comments
Labels
area-Interop-coreclr design-discussion Ongoing discussion about design without consensus

Comments

@halter73
Copy link
Member

halter73 commented Feb 2, 2017

The following app will print "Handled exception from reverse P/Invoke" on Windows and then exit. On Linux it will crash with an unhandled exception. I tested this using Microsoft.NETCore.App 1.1 on both platforms. I did not test this on macOS or with other versions of the dotnet runtime.

using System;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    public class Program
    {
        public const int AsyncType = 1;
        public const int DefaultRunMode = 0;

        public delegate void uv_async_cb(IntPtr handle);

        [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
        public static extern int uv_loop_size();

        [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
        public static extern int uv_loop_init(IntPtr loop);

        [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
        public static extern int uv_run(IntPtr loop, int mode);

        [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
        public static extern int uv_handle_size(int handleType);

        [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
        public static extern int uv_async_init(IntPtr loop, IntPtr async, uv_async_cb callback);

        [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
        public static extern int uv_async_send(IntPtr async);

        public static void Main(string[] args)
        {
            var loop = Marshal.AllocHGlobal(uv_loop_size());
            var async = Marshal.AllocHGlobal(uv_handle_size(AsyncType));

            uv_loop_init(loop);
            uv_async_init(loop, async, _ =>
            {
                throw new Exception();
            });

            // Tell uv_run to call the async callback that throws
            uv_async_send(async);

            try
            {
                uv_run(loop, DefaultRunMode);
            }
            catch
            {
                Console.WriteLine("Handled exception from reverse P/Invoke.");
            }
        }
    }
}

Windows output:

> dotnet run
Handled exception from reverse P/Invoke.

Linux output:

$ dotnet run
Project ConsoleApp2 (.NETCoreApp,Version=v1.1) was previously compiled. Skipping compilation.

Unhandled Exception: System.Exception: Exception of type 'System.Exception' was thrown.
   at ConsoleApp1.Program.<>c.<Main>b__9_0(IntPtr _) in /home/shalter/ConsoleApp2/Program.cs:line 39
   at ConsoleApp1.Program.uv_run(IntPtr loop, Int32 mode)
   at ConsoleApp1.Program.Main(String[] args) in /home/shalter/ConsoleApp2/Program.cs:line 47

We expect to be able to catch and handle these exceptions in KestrelHttpServer.

@parjong
Copy link
Contributor

parjong commented Feb 2, 2017

Seems to be related with #6820.

@janvorli
Copy link
Member

janvorli commented Feb 6, 2017

@halter73 this is by design in CoreCLR and we are going to make it behave the same way on Windows too (see #7086). For some details, please see dotnet/coreclr#7652 (comment).

@DemiMarie
Copy link

Does that mean that one should wrap every callback in (pseudo-C#)

try
{
    some code that might throw
}
catch (System.Object o)
{
    if (o is System.Exception) {
        // log a stack trace maybe?
    }
}

@DemiMarie
Copy link

@halter73 note that libuv is likely in an inconsistent state even on Windows – as a C library it is not designed to handle this scenario.

@janvorli
Copy link
Member

janvorli commented Feb 6, 2017

@DemiMarie yes, the exceptions need to be caught at that boundary. What the code does when the exception is caught is specific to the application / library. It might be logging and then ignoring the exception, it might be logging and failing fast or converting the exception to some kind of status that's propagated to the managed code that called the native code that called the faulting managed code.

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Interop-coreclr design-discussion Ongoing discussion about design without consensus
Projects
None yet
Development

No branches or pull requests

5 participants