Runtime: Excepción a través de PInvoke

Creado en 26 jul. 2017  ·  3Comentarios  ·  Fuente: dotnet/runtime

Estoy probando el siguiente código.

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 se basa en el siguiente código fuente C

#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 sale con una excepción no controlada de la siguiente manera.

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$ 

aquí está 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

¿Es este comportamiento normal que el bloque catch en la función principal no capture la excepción?

Comentario más útil

Una de las razones es que realmente no sabemos cómo propagar la excepción a través del código nativo que llamó a la devolución de llamada administrada, ya que no tenemos idea de qué tipo de código era. Podría haber sido código C, código C++, código ASM o, de hecho, cualquier otro código de idioma. Si solo omitiéramos esos marcos y fuera, por ejemplo, C++, no estaríamos llamando a los destructores de objetos de pila, por lo que posiblemente perderíamos memoria o abandonaríamos bloqueos bloqueados, etc. sin querer O incluso puede romper algunos tiempos de ejecución que no están listos para procesar excepciones.

Todos 3 comentarios

El cruce de excepciones administrado hasta el límite nativo (como en su caso, cuando se llama a una devolución de llamada desde el código nativo y genera una excepción) no se admite intencionalmente en dotnet core. Deberá capturar todas las excepciones en sus devoluciones de llamada a las que llama desde el código nativo.

Una de las razones es que realmente no sabemos cómo propagar la excepción a través del código nativo que llamó a la devolución de llamada administrada, ya que no tenemos idea de qué tipo de código era. Podría haber sido código C, código C++, código ASM o, de hecho, cualquier otro código de idioma. Si solo omitiéramos esos marcos y fuera, por ejemplo, C++, no estaríamos llamando a los destructores de objetos de pila, por lo que posiblemente perderíamos memoria o abandonaríamos bloqueos bloqueados, etc. sin querer O incluso puede romper algunos tiempos de ejecución que no están listos para procesar excepciones.

Muchísimas gracias.

¿Fue útil esta página
0 / 5 - 0 calificaciones