Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# P/Invoke:致命错误。无效程序:试图从运行时类型安全代码调用NativeCallable方法_C#_Linux_Signals_Pinvoke - Fatal编程技术网

C# P/Invoke:致命错误。无效程序:试图从运行时类型安全代码调用NativeCallable方法

C# P/Invoke:致命错误。无效程序:试图从运行时类型安全代码调用NativeCallable方法,c#,linux,signals,pinvoke,C#,Linux,Signals,Pinvoke,我正试图使用libstd中的sigaction在Linux系统(Ubuntu)的后台任务中捕获kill信号。以下是我的程序类和DllImport声明: using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace Signal { class Program { static void Main

我正试图使用libstd中的sigaction在Linux系统(Ubuntu)的后台任务中捕获kill信号。以下是我的程序类和DllImport声明:

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace Signal
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var pid = LibStd.GetPid();
            Console.WriteLine($"PID: {pid}");

            var sa = new Sigaction()
            {
                Handler = SignalHandler
            };

            LibStd.SigEmptySet(sa.Mask);
            var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(sa));
            Marshal.StructureToPtr(sa, ptr, true);

            _ = Task.Run(async() =>
            {
                while (true)
                {
                    // Check SIGUSR1
                    if (LibStd.Sigaction(10, ptr, IntPtr.Zero) == -1)
                    {
                        // error
                    }

                    await Task.Delay(1);
                }
            });

            while (true)
            {
                // Do something
            }
        }

        static LibStd.SignalHandler SignalHandler = new LibStd.SignalHandler(Handler);

        static void Handler(int sig)
        {
            Console.WriteLine($"RECEIVED SIGNAL {sig}");
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct Sigaction
    {
        public LibStd.SignalHandler Handler;
        public IntPtr Mask;
        public int Flags;
    }

    internal static class LibStd
    {
        private const string LibName = "c";

        [DllImport(LibName, EntryPoint = "getpid")]
        internal static extern int GetPid();

        [DllImport(LibName, EntryPoint = "sigaction", CallingConvention = CallingConvention.Cdecl)]
        internal static extern int Sigaction(int sig, IntPtr act, IntPtr oldact);

        [DllImport(LibName, EntryPoint = "sigemptyset", CallingConvention = CallingConvention.Cdecl)]
        internal static extern int SigEmptySet(IntPtr mask);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal delegate void SignalHandler(int t);
    }
}
我需要在后台检查信号,因为我想在将来把这段代码放到桌面GUI应用程序中,这样信号处理就不会阻塞UI线程。 但是,当我运行这个程序时,调用
kill-SIGUSR1
它会向控制台输出以下错误: 致命错误。无效程序:试图从运行时类型安全代码调用NativeCallable方法。 如果我将信号处理放入main
while(true){}
循环,它将按预期工作。

如果有人能帮我修一下,那就太好了。谢谢你对Ubuntu 18的支持,我发现所需的结构是

[StructLayout(LayoutKind.Sequential)]
internal struct Sigaction
{
    public LibStd.SignalHandler Handler;
    public IntPtr Mask;
    public int Flags;
    public LibStd.SignalHandler sa_restorer;
}
考虑不启动信号处理线程

static private void ListenToSignal()
{
    var sa = new Sigaction()
    {
        Handler = SignalHandler
    };

    LibStd.SigEmptySet(sa.Mask);
    var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(sa));
    Marshal.StructureToPtr(sa, ptr, true);

    if (LibStd.Sigaction(10, ptr, IntPtr.Zero) == -1)
    {
        Console.WriteLine("Sigaction -1");
    }
    Console.WriteLine("Sigaction done");        
}

这将在主线程上设置处理。当信号到达时,它也会被处理。无需继续轮询Sigaction

您可能应该使用async main并等待任务,或者使用.Wait()。如果没有这一点,您的主要方法可能会在任务完成之前结束。不确定这是否与你的问题有关,但可能是。@JonasH,不,对不起。main方法在无限循环中,所以它不会在任务执行之前完成。这个问题与P/E有关啊,我也是用同样的方法来解决的。谢谢你的帮助