4

I'm writing a .NET 4.5 console application that use external dynamic libraries and I don't have access to the sources of those libraries. The problem is that those DLLs may raise a segmentation fault signal and when this happens, the whole process is immediately terminated. My current solution is to run this dll-dependent code as a separate process, and then retrieve the result, but I've noticed that this solution is not very efficient.

To illustrate my issue, I've made a sample code:

#include <signal.h>
__declspec(dllexport) void err(void)
{
    raise(SIGSEGV);
}
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp
{
    class Program
    {
        [DllImport("segFault.dll")]
        extern static void err();

        static void Main(string[] args)
        {
            try
            {
                Console.Write("started");
                err();
                Console.WriteLine("running");
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception:" + ex.Message);
            }
        }
    }
}

With such setup, I'll never reach the "running" nor the "Exception:" code, because the whole process will be terminated while reaching the segfault signal. I have tried to mess with Application Domains but also without any great success.

using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace ConsoleApp
{
    class Program
    {
        [DllImport("segFault.dll")]
        extern static void err();

        static void Main(string[] args)
        {
            if (!args.Any())
            {
                AppDomain.CreateDomain("testdomain")
                    .ExecuteAssemblyByName("ConsoleApp", "1");
                Console.ReadKey();
            }

            try
            {
                Console.Write("started");
                err();
                Console.WriteLine("running");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception:" + ex.Message);
            }
        }
    }
}

I have also tried to bridge the P/Invoke execution using a simple wrapper and then dynamically load that wrapper to the main executable, and also, without any success.

// Bridge.dll
using System.Runtime.InteropServices;
namespace Bridge
{
    public static class Bridge
    {
        [DllImport("segFault.dll")]
        public static extern void err();
    }
}

// Main Executable
using System;
using System.Reflection;
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly.Load("Bridge").GetType("Bridge.Bridge")
                .GetMethod("err").Invoke(null, null);
            Console.WriteLine("This code will not execute");
        }
    }
}

erexo
  • 503
  • 1
  • 6
  • 24
  • You could try installing your custom handler for `SIGSEGV` as described for instance [in this answer](https://stackoverflow.com/a/32799720/2846483), but you have to know what you are doing. `SIGSEGV` means the unamaged memory of your process might be "damaged", so your whole application or even the runtime might be in a corrupted/undefined state then. – dymanoid Jul 15 '19 at 14:49
  • @dymanoid sadly this answer is all about catching the segfault signal using the C language, I do not have the ability to modify my DLLs so I need to take care about that in the C# language. – erexo Jul 15 '19 at 14:58
  • You still can create a small native module and load into your app without touching the DLLs. The `SIGSEGV` is handled at process level, not at module level. – dymanoid Jul 15 '19 at 19:16
  • can you please elaborate further on that topic? How can I wrap already compiled C++ DLL into module to execute it using C# assembly? – erexo Jul 16 '19 at 08:11
  • You don't need that. Just create a new native module, use the code from the answer I referenced (it installs the signal handler for the *whole process*) and then just call the "installer" function of that module using P/Invoke in your managed application. – dymanoid Jul 16 '19 at 13:11

0 Answers0