Runtime: Ausnahme durch PInvoke

Erstellt am 26. Juli 2017  ·  3Kommentare  ·  Quelle: dotnet/runtime

Ich teste den folgenden Code.

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("libupcall.so")]
    public static extern void register_callback(Callback cb);

    [DllImport("libupcall.so")]
    public static extern void upcall();

    public static void MyStaticCallback(int val)
    {
        throw new Exception("error");
    }

    public delegate void Callback(int var);
    static Callback cbMyStaticCallback = MyStaticCallback;  

    static void Main(string[] args)
    {
        try {
            register_callback(MyStaticCallback); 
            upcall();                

        } catch (Exception e) {
            Console.WriteLine("Catch clause caught : {0} \n", e.Message);
        }
    }
}

libupcall.so basiert auf dem folgenden C-Quellcode

#include <stdio.h>

typedef void (*callback)(int val);

callback gCB;

extern void register_callback(callback cb)
{
    printf("register_callback:%p ----\n", (void *)cb);
    gCB = cb;
}
extern void upcall()
{
    static int c = 0;
    printf("upcall ----\n");
    gCB(c++);
}

dotnet run wird mit einer nicht behandelten Ausnahme wie folgt beendet.

twoflower@js2-desktop:~/dev/complexexception$ sudo dotnet run
register_callback:0x7f3a041f407c ----
upcall ----

Unhandled Exception: System.Exception: error
   at Program.MyStaticCallback(Int32 val) in /home/twoflower/dev/complexexception/Program.cs:line 14
   at Program.upcall()
   at Program.Main(String[] args) in /home/twoflower/dev/complexexception/Program.cs:line 24
twoflower@js2-desktop:~/dev/complexexception$ 

hier ist corefile bt.

* thread dotnet/coreclr#1: tid = 0, 0x00007fda93b26428 libc.so.6`__GI_raise(sig=6) + 56 at raise.c:54, name = 'dotnet', stop reason = signal SIGABRT
  * frame #0: 0x00007fda93b26428 libc.so.6`__GI_raise(sig=6) + 56 at raise.c:54
    frame dotnet/coreclr#1: 0x00007fda93b2802a libc.so.6`__GI_abort + 362 at abort.c:89
    frame dotnet/coreclr#2: 0x00007fda9326258c libcoreclr.so`??? + 124
    frame dotnet/coreclr#3: 0x00007fda9326148b libcoreclr.so`??? + 235
    frame dotnet/coreclr#4: 0x00007fda92f0b893 libcoreclr.so`??? + 531
    frame dotnet/coreclr#5: 0x00007fda92f0cd71 libcoreclr.so`??? + 593
    frame dotnet/coreclr#6: 0x00007fda92fcaae3 libcoreclr.so`??? + 51
    frame dotnet/coreclr#7: 0x00007fda93ecb263 libgcc_s.so.1`_Unwind_RaiseException(exc=0x0000000002467530) + 115 at unwind.inc:113
    frame dotnet/coreclr#8: 0x00007fda9446790c libstdc++.so.6`__cxa_throw + 92
    frame dotnet/coreclr#9: 0x00007fda9322749d libcoreclr.so`??? + 77
    frame dotnet/coreclr#10: 0x00007fda92fd781e libcoreclr.so`??? + 273
    frame dotnet/coreclr#11: 0x00007fda88e4b7b2 libupcall.so`upcall + 45 at upcall.c:16
    frame dotnet/coreclr#12: 0x00007fda19d85ae6
    frame dotnet/coreclr#13: 0x00007fda19d8588e
    frame dotnet/coreclr#14: 0x00007fda92fd67b7 libcoreclr.so`??? + 124
    frame dotnet/coreclr#15: 0x00007fda92eec630 libcoreclr.so`??? + 1264

Ist das normale Verhalten, dass der Catch-Block in der Main-Funktion keine Ausnahme abfängt?

Hilfreichster Kommentar

Einer der Gründe ist, dass wir nicht wirklich wissen, wie wir eine Ausnahme durch den nativen Code, der den verwalteten Rückruf aufgerufen hat, weitergeben, da wir keine Ahnung haben, um welche Art von Code es sich handelt. Es könnte C-Code, C++-Code, ASM-Code oder tatsächlich jeder andere Sprachcode gewesen sein. Wenn wir diese Frames einfach überspringen würden und es zB C++ wäre, würden wir keine Destruktoren von Stack-Objekten aufrufen, wodurch möglicherweise Speicher verloren geht oder gesperrte Sperren aufgegeben werden usw. Wenn wir versuchen würden, eine vordefinierte C++-Ausnahme dadurch zu werfen, könnte der native Code sie verschlucken unbeabsichtigt. Oder es kann sogar einige Laufzeiten unterbrechen, die nicht bereit sind, Ausnahmen zu verarbeiten.

Alle 3 Kommentare

Ausnahmeüberschreitungen, die von nativen Grenzen verwaltet werden (wie in Ihrem Fall, wenn ein Rückruf von nativem Code aufgerufen wird und eine Ausnahme auslöst), werden absichtlich nicht auf dotnet core unterstützt. Sie müssen alle Ausnahmen in Ihren Rückrufen abfangen, die Sie aus nativem Code aufrufen.

Einer der Gründe ist, dass wir nicht wirklich wissen, wie wir eine Ausnahme durch den nativen Code, der den verwalteten Rückruf aufgerufen hat, weitergeben, da wir keine Ahnung haben, um welche Art von Code es sich handelt. Es könnte C-Code, C++-Code, ASM-Code oder tatsächlich jeder andere Sprachcode gewesen sein. Wenn wir diese Frames einfach überspringen würden und es zB C++ wäre, würden wir keine Destruktoren von Stack-Objekten aufrufen, wodurch möglicherweise Speicher verloren geht oder gesperrte Sperren aufgegeben werden usw. Wenn wir versuchen würden, eine vordefinierte C++-Ausnahme dadurch zu werfen, könnte der native Code sie verschlucken unbeabsichtigt. Oder es kann sogar einige Laufzeiten unterbrechen, die nicht bereit sind, Ausnahmen zu verarbeiten.

Vielen Dank.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

yahorsi picture yahorsi  ·  3Kommentare

aggieben picture aggieben  ·  3Kommentare

iCodeWebApps picture iCodeWebApps  ·  3Kommentare

Timovzl picture Timovzl  ·  3Kommentare

bencz picture bencz  ·  3Kommentare