- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
在我的程序中,我使用 signalfd
来处理信号并将其与 poll
结合用于异步 IO。下面是我的代码:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/signalfd.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <poll.h>
#include <assert.h>
#include <errno.h>
volatile sig_atomic_t cont = 1;
volatile sig_atomic_t usrcnt = 0;
volatile sig_atomic_t susrcnt = 0;
volatile sig_atomic_t wsig = 0;
volatile sig_atomic_t wtid = 0;
int GetCurrentThreadId()
{
return syscall(__NR_gettid);
}
void Segv1(int p1, siginfo_t * p2, void * p3)
{
//printf("SIGSEGV signal on illegal memory access handled by thread: %d\n", GetCurrentThreadId());
wtid = GetCurrentThreadId();
wsig = SIGSEGV;
_exit(SIGSEGV);
}
void Fpe1(int p1 , siginfo_t * p2, void * p3)
{
//printf is only for test.
//printf("FPE signal handled by thread: %d\n", GetCurrentThreadId());
wtid = GetCurrentThreadId();
wsig = SIGFPE;
_exit(SIGFPE);
}
void User1(int p1 , siginfo_t * p2, void * p3)
{
printf("User signal 1 handled by thread: %d\n", GetCurrentThreadId());
++susrcnt;
wtid = GetCurrentThreadId();
wsig = SIGUSR1;
}
void* ThreadFunc (void* d)
{
//Let us use signalfd.
int sfd;
sigset_t mask;
/* We will handle SIGTERM and SIGINT. */
sigemptyset (&mask);
sigaddset (&mask, SIGUSR1);
/* Create a file descriptor from which we will read the signals. */
sfd = signalfd (-1, &mask, 0);
if (sfd < 0) {
printf ("signalfd failed with %d\n", errno);
return NULL;
}
pthread_sigmask(SIG_BLOCK, &mask, NULL);
/* This is the main loop */
struct pollfd pfd[1];
int ret;
ssize_t bytes;
pfd[0].fd = sfd;
pfd[0].events = POLLIN | POLLERR | POLLHUP;
for (;;) {
ret = poll(pfd, 1, -1);
/* Bail on errors (for simplicity) */
assert(ret > 0);
assert(pfd[0].revents & POLLIN);
/* We have a valid signal, read the info from the fd */
struct signalfd_siginfo info;
bytes = read(sfd, &info, sizeof(info));
assert(bytes == sizeof(info));
unsigned sig = info.ssi_signo;
unsigned user = info.ssi_uid;
if (sig == SIGUSR1) {
++usrcnt;
printf ("Got SIGUSR1 by POLL in thread: %d: Handler count: %d, %d\n", GetCurrentThreadId(), susrcnt, usrcnt);
}
}
/* Close the file descriptor if we no longer need it. */
close (sfd);
return NULL;
}
int main()
{
const int numthreads = 1;
sigset_t sset;
struct sigaction act;
int sleepval = 15;
int pid;
int i;
int * a = 0;
//*a = 1;
int c=0;
//c = 0;
int b;
printf("My PID: %d\n", getpid());
printf("SIGSEGV: %d\nSIGFPE: %d\nSIGUSR1: %d\n", SIGSEGV, SIGFPE, SIGUSR1);
//Create a thread for signal
memset(&act, 0, sizeof act);
act.sa_sigaction = User1;
act.sa_flags = SA_SIGINFO;
//Set Handler for SIGUSR1 signal.
if(sigaction(SIGUSR1, &act, NULL)<0) {
fprintf(stderr, "sigaction failed\n");
return 1;
}
//Set handler for SIGSEGV signal.
act.sa_sigaction = Segv1;
sigaction(SIGSEGV, &act, NULL);
//Set handler for SIGFPE (floating point exception) signal.
act.sa_sigaction = Fpe1;
sigaction(SIGFPE, &act, NULL);
sigemptyset(&sset);
sigaddset(&sset, SIGUSR1);
sigprocmask(SIG_UNBLOCK, &sset, NULL);
pthread_t tid[numthreads];
for(i=0;i<numthreads;++i)
pthread_create(&tid[i], NULL, ThreadFunc, NULL);
//Block the signal for main thread so that other thread handles the the signal.
pthread_sigmask(SIG_BLOCK, &sset, NULL);
sleep(numthreads/2);
//Raise user signal SIGUSR1.
//raise(SIGUSR1);
pid = fork();
if(pid) {
while(sleepval) {
sleepval = sleep(sleepval);
if(sleepval)
switch(wsig) {
case SIGSEGV:
printf("[Main] Segmenation fault in thread: %d\n", wtid);
exit(1);
break;
case SIGFPE:
printf("[Main] Floating point exception in thread: %d\n", wtid);
exit(1);
break;
case SIGUSR1:
printf("[Main] User 1 signal in thread: %d\n", wtid);
break;
default:
printf("[Main] Unhandled signal: %d in thread: %d\n", wsig, wtid);
break;
}
}
} else {
sleep(1); //To avoid race between signal handler and signal fd.
for(i=0;i<10;++i) {
//If sleep is not used, signal SIGUSR1 will be handled one time in parent
//as other signals will be ignored while SIGUSR1 is being handled.
sleep(1);
//Problem is here. When the sleep(1) is commented out, it missed the signals.
kill(getppid(), SIGUSR1);
}
return 0;
}
return 0;
}
在程序中,进程生成一个线程,该线程创建 signalfd
并开始使用 poll
。然后进程产生一个子进程,该子进程将 SIGUSR1
发送到父进程。当以 1s 的间隔发送信号时,它会处理所有信号。然而,当 sleep
被移除时,它错过了通知。
我想知道如果 signalfd 正在处理相同的信号,它是否也会丢弃信号通知。另外,信号处理程序和 signalfd
之间的优先顺序是什么?
最佳答案
如果一个进程有多个标准(即:非实时)信号挂起,操作系统可能会决定将多个相同类型的信号合并为一个。
来自 POSIX :
2.4.1 Signal Generation and Delivery
[...]
If a subsequent occurrence of a pending signal is generated, it is implementation-defined as to whether the signal is delivered or accepted more than once in circumstances other than those in which queuing is required.
默认情况下,标准信号不排队。使标准信号排队的唯一方法是使用 sigqueue()
发出它们.
关于c - signalfd() 遗漏信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25717766/
是否有 signalfd 的替代方案(在 Mac OS X 上不可用)?我正在使用 select 复用 I/O,并希望以某种同步方式接收信号。 最佳答案 man kqueue 并在那里查找 EVFIL
在我的程序中,我使用 signalfd 来处理信号并将其与 poll 结合用于异步 IO。下面是我的代码: #include #include #include #include #inclu
在 signalfd 上调用 read() 是否会消耗 SIGCHLD?或者我需要在之后调用 waitid() 来消费吗? 我通过调用 epoll_wait() 在 signalfd 上接收到可读事件
我的系统是ubuntu 12.04。我修改了 man 2 signalfd 的示例,并在示例中添加了 sigaddset(&mask, SIGSEGV)。但是生成 SIGSEGV 时我无法获得输出。
为特定信号指定处理程序的经典方法是通过 sigaction。 Linux 还提供了 signalfd 功能,我们可以在其中将信号连接到文件描述符,然后将 select/(e)poll 应用于该描述符,
三种新的fd加入linux内核的的版本: signalfd:2.6.22 timerfd:2.6.25 eventfd:2.6.22 三种fd的意义: lsignalfd 传统的处理信号
我正在使用套接字和系统调用编写自己的echo 服务器。我使用 epoll 同时与许多不同的客户端一起工作,并且与客户端完成的所有操作都是非阻塞的。当服务器开启且不执行任何操作时,它处于 epoll_w
我创建一个 sigset_t 并将其设置为空,然后向其添加 SIGCHLD,然后将其设置为 BLOCK: sigset_t sigmask; sigemptyset (&sigmask); si
我知道 linux 操作系统中的 signalfd()、eventfd() api。但是,我在其他操作系统(SunOS、Aix、HP)中找不到这个 api。 它只支持 Linux 吗?? 最佳答案 s
我是一名优秀的程序员,十分优秀!