0
votes

I have a console app running .Net 4.6.1 on mono in a Docker Container and it runs fine. When developing the app further I'm looking into responding to unix signals using the Nuget-package Mono.Posix.

According to the Mono documentation it is recommended running the UnixSignal handling in a separate thread.

So I'm trying to do this like the code below:

public void Run()
{
    var signalHandler = new Thread(new ThreadStart(ListenToSignal));
    signalHandler.Start();
}

private void ListenToSignal()
{
    var signals = new List<UnixSignal>() {
        new UnixSignal (Mono.Unix.Native.Signum.SIGHUP),
        new UnixSignal (Mono.Unix.Native.Signum.SIGINT),
        new UnixSignal (Mono.Unix.Native.Signum.SIGQUIT),
        new UnixSignal (Mono.Unix.Native.Signum.SIGTERM)
    };

    int index = UnixSignal.WaitAny(signals.ToArray());
    var signal = signals[index].Signum;
    Console.WriteLine($"Terminate signal was called: {signal}");
}

When starting the application it throws a ArgrumentException:

Unhandled Exception: System.ArgumentException: Unable to handle signal Parameter name: signum at Mono.Unix.UnixSignal..ctor (Signum signum) <0x40433de0 + 0x00097> in :0 at (wrapper remoting-invoke-with-check) Mono.Unix.UnixSignal:.ctor (Mono.Unix.Native.Signum) at MangoFareScrapingGenericClient.Scraping.ListenToSignal () <0x404339e0 + 0x00117> in :0 at System.Threading.ThreadHelper.ThreadStart_Context (System.Object state) <0x7f20f10b1010 + 0x00099> in :0 at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, Boolean preserveSyncCtx) <0x7f20f10af850 + 0x0016e> in :0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, Boolean preserveSyncCtx) <0x7f20f10af820 + 0x00020> in :0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state) <0x7f20f10af770 + 0x00059> in :0 at System.Threading.ThreadHelper.ThreadStart () <0x7f20f10b11d0 + 0x0002e> in :0

If I look on Github for the specific code it looks like signal_info is a IntPtr.Zero which throws the exception.

public UnixSignal (Signum signum)
{
    this.signum = NativeConvert.FromSignum (signum);
    this.signal_info = install (this.signum);
    if (this.signal_info == IntPtr.Zero) {
        throw new ArgumentException ("Unable to handle signal", "signum");
    }
}
1

1 Answers

2
votes

SIGTERM and SIGINT support was added to Docker in ~2013 (I remember the pull-request because I needed that support in a deployment)

So I'm assuming either SIGQUIT or SIGHUP is failing to be installed.

But, since you did not say which signal is returning a IntPtr.Zero and thus throwing the exception, I would try installing each signal on its own to find the one that is not supported in your Ubuntu Docker environment.

At that point, you can test that signal under a straight C program to determine if it runs ok as it might be a problem in the Mono runtime running under Docker.

Plus you can try/catch your UnixSignal.WaitAny and gracefully degrade your signal processing and write a log message about the offending signal.