【发布时间】: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
【问题讨论】:
标签: c# c++ linux .net-core signals