linux 平台上 C# 中的自定义 posix 信号不起作用
Posted
技术标签:
【中文标题】linux 平台上 C# 中的自定义 posix 信号不起作用【英文标题】:Custom posix signal in C# on a linux platform does not work 【发布时间】:2021-08-16 05:20:07 【问题描述】:问题
我正在尝试将 linux 中的信号发送到 Linux dotnet 核心中的 C# 中的线程。我的测试代码适用于 SIGARAM,但不适用于映射到 SIGRTMIN# 的自定义信号。当主线程引发自定义信号时,线程上的sigwait
永远不会返回。
C++ 版本运行良好。 C++ 和 C# 版本几乎相同。谁能弄清楚为什么它不起作用?
我的最终目标是从设备驱动程序中捕获信号。
C++ 版本
//https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/apis/sigwaiti.htm
//g++ -Wall -O2 example.cpp -o example -pthread
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <thread>
void catcher( int sig )
printf( "Signal catcher called for signal %d\n", sig );
void timestamp( const char *str )
time_t t;
time( &t );
printf( "The time %s is %s\n", str, ctime(&t) );
void on_sigusr1(int sig)
// Note: Normally, it's not safe to call almost all library functions in a
// signal handler, since the signal may have been received in a middle of a
// call to that function.
printf("SIGUSR1 received!\n");
#define SIG_SYSTEM (SIGRTMIN+7)
void run()
struct sigaction sigact;
sigset_t waitset;
siginfo_t info;
sigemptyset( &sigact.sa_mask );
sigact.sa_flags = 0;
sigact.sa_handler = catcher;
sigaction( SIG_SYSTEM, &sigact, NULL );
sigemptyset( &waitset );
sigaddset( &waitset, SIG_SYSTEM );
sigprocmask( SIG_BLOCK, &waitset, NULL );
timestamp( "before sigwaitinfo()" );
// int result = sigwaitinfo( &waitset, &info );
int sig;
int result = sigwait( &waitset, &sig );
if( sig == SIG_SYSTEM )
printf( "sigwaitinfo() returned for signal %d\n",
info.si_signo );
else
printf( "sigwait() sig %d\n", sig );
printf( "sigwait() returned code %d\n", result );
printf( "sigwait() returned error number %d\n", errno );
perror( "sigwait() function failed\n" );
timestamp( "after sigwaitinfo()" );
int main( int argc, char *argv[] )
int result = 0;
signal(SIG_SYSTEM, &on_sigusr1);
sigset_t waitset;
sigemptyset( &waitset );
sigaddset( &waitset, SIG_SYSTEM );
sigprocmask( SIG_BLOCK, &waitset, NULL );
std::thread tx(run);
sleep(5);
//alarm( 5 );
//result = raise(SIG_SYSTEM);
result = kill(getpid(), SIG_SYSTEM);
printf( "kill(%d) %d\n", SIG_SYSTEM, result);
tx.join();
return( result );
C#版本
但是 C# 中的测试程序不起作用。
using System;
using static Tmds.Linux.LibC;
using Tmds.Linux;
using System.Runtime.InteropServices;
delegate void SignalCallback(int sig);
namespace example
class Program
static void catcher(int sig)
Console.WriteLine($"Signal catcher called for signal sig");
static void timestamp(string str)
Console.WriteLine($"The time str is DateTime.Now");
static System.Threading.Thread Thread;
static int SIG_SYSTEM = SIGRTMIN + 7;
static unsafe void Run()
int result = 0;
sigaction sigact = new sigaction();
sigset_t waitset = new sigset_t();
siginfo_t info = new siginfo_t();
sigset_t* ptr = &sigact.sa_mask;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
SignalCallback callback = new SignalCallback(catcher);
sigact.sa_handler = (void*)Marshal.GetFunctionPointerForDelegate(callback);
sigaction(SIG_SYSTEM, &sigact, null);
sigemptyset(&waitset);
sigaddset(&waitset, SIG_SYSTEM);
sigprocmask(SIG_BLOCK, &waitset, null);
timestamp("before sigwaitinfo()");
//result = sigwaitinfo(&waitset, &info);
int sig;
result = sigwait(&waitset, &sig);
// after it's last usage by unmanaged code
GC.KeepAlive(callback);
if (sig == SIG_SYSTEM)
Console.WriteLine($"sigwaitinfo() returned for signal info.si_signo");
else
Console.WriteLine($"sigwait() sig sig");
Console.WriteLine($"sigwait() returned code result");
Console.WriteLine($"sigwait() returned error number errno");
Console.WriteLine("sigwait() function failed");
timestamp("after sigwaitinfo()");
static unsafe void Main(string[] args)
sigset_t waitset = new sigset_t();
sigemptyset(&waitset);
sigaddset(&waitset, SIG_SYSTEM);
sigprocmask(SIG_BLOCK, &waitset, null);
Thread = new System.Threading.Thread(Run);
Thread.Start();
//alarm(10);
sleep(5);
int result = kill(getpid(), SIG_SYSTEM);
Console.WriteLine($"kill(SIG_SYSTEM) result");
Thread.Join();
环境
VisualStudio 专业版 2019 16.9.4 dotnet 核心 SDK 3.1 WSL 上的 Ubuntu Tmds.Linux 0.5.0【问题讨论】:
【参考方案1】:我能够得到一个写入一个小 .so 文件的信号。
static void (*_callback)(int, int);
void catcher(int sig, siginfo_t* info, void* context)
int* sival_int = &info->si_int;
_callback(sig, sival_int[1]);
extern "C" void setaction(int sig, void *callback)
_callback = (void(*)(int, int))callback;
struct sigaction sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = catcher;
sigaction(sig, &sigact, NULL);
delegate void SignalCallback(int sig, int info);
static SignalCallback cb = Callback;
[DllImport("signalhandle.so")]
static extern void setaction(int sig, SignalCallback callback);
//Call this on the main thread.
public static void Start()
setaction(SIG_SYSTEM, cb);
private static void Callback(int sig, int info)
【讨论】:
以上是关于linux 平台上 C# 中的自定义 posix 信号不起作用的主要内容,如果未能解决你的问题,请参考以下文章