Artyom Sokolov
Artyom Sokolov

Reputation: 2405

Apache Ignite.NET and AppDomain.CurrentDomain.ProcessExit

Consider class, utilising Apache Ignite.NET library

public interface ICluster
{
    void Join();

    void Leave();
}

public class ApacheIgniteClusterImpl : ICluster
{
    private IIgnite Ignite { get; set; }

    private int MulticastPort { get; }

    private int ThinClientPort { get; }

    public ApacheIgniteClusterImpl(int multicastPort = 47401, int thinClientPort = 10800)
    {
        MulticastPort = multicastPort;
        ThinClientPort = thinClientPort;
    }

    public void Join()
    {
        if (Ignite != null)
        {
            return;
        }

        var configuration = new IgniteConfiguration
        {
            ClientConnectorConfiguration = new ClientConnectorConfiguration
            {
                Port = ThinClientPort,
            },
            DiscoverySpi = new TcpDiscoverySpi
            {
                IpFinder = new TcpDiscoveryMulticastIpFinder()
                {
                    MulticastPort = MulticastPort,
                }
            },
            JvmOptions = new List<string>()
            {
                "-DIGNITE_NO_SHUTDOWN_HOOK=true",
            },
        };

        // Start
        Ignite = Ignition.Start(configuration);
    }

    public void Leave()
    {
        Ignition.Stop(null, true);
        Ignite = null;
    }
}

Normally, in .NET Standard we are allowed to hook into AppDomain.CurrentDomain.ProcessExit event where we could do our cleanup stuff. However, once JVM is created by Apache Ignite.NET AppDomain.CurrentDomain.ProcessExit will never be fired when I kill console application on MacOS with kill <pid>.

I've done some research while debugging, and found out that it will happen somewhere after private static Jvm CreateJvm(IgniteConfiguration cfg, ILogger log) has been called.

Any idea what happens there and if there any chance we can hook into AppDomain.CurrentDomain.ProcessExit?

UPD: Neither AppDomain.CurrentDomain.DomainUnload nor System.Runtime.Loader.AssemblyLoadContext.Unloading will work too.

Upvotes: 3

Views: 178

Answers (2)

Artyom Sokolov
Artyom Sokolov

Reputation: 2405

According to Oracle's Java Documentation:

Applications embedding the JVM frequently need to trap signals such as SIGINT or SIGTERM, which can lead to interference with the JVM signal handlers. The -Xrs option is available to address this issue. When -Xrs is used, the signal masks for SIGINT, SIGTERM, SIGHUP, and SIGQUIT are not changed by the JVM, and signal handlers for these signals are not installed.

Thus, after slightly modifying initial class I was able to handle AppDomain.CurrentDomain.ProcessExit and Console.CancelKeyPress

// ...
JvmOptions = new List<string>()
{
    "-Xrs", // <--------------------
    "-DIGNITE_NO_SHUTDOWN_HOOK=true",
},
// ...

Upvotes: 1

Pavel Tupitsyn
Pavel Tupitsyn

Reputation: 8986

ProcessExit is not guaranteed to be called.

I believe Ignite.NET has nothing to do with this. I have checked this (not referencing or starting Ignite) and if you terminate the process forcibly, the handler is not called.

Upvotes: 2

Related Questions