msgrcv-SA_RESTART标志不起作用 [英] msgrcv - SA_RESTART flag doesn't work
问题描述
我的代码有问题,该代码使用IPC队列在线程之间进行通信. 我需要安全地处理SIGINT-在关闭之前,让SIGINT出现时,程序要完成所有活动线程.但是,我遇到了解决问题的严重问题,因为即使对带有标志SA_RESTART的SIGINT进行了签名,msgrcv函数也会收到EINTR错误.
There is something wrong with my code that uses IPC queue to communicate between threads. I need to handle SIGINT safely - let program finish all active threads when SIGINT appeared before shutting down. Though, I have serious problem of finding solution because even with sigaction for SIGINT with flag SA_RESTART the msgrcv function is getting EINTR error.
我的问题是-除了msgrcv函数,有什么方法可以避免EINTR 在某些如果"中指定错误条件,例如:
My question is - is there any way to avoid EINTR with msgrcv function other than specifying the error condition in some "if" such as:
if (msgrcv<0){
if (errno == EINTR){
errno = 0;
}
}
这里确实是我程序的简化版本,用于演示问题:
Here is really simplified version of my program to demonstate problem :
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/msg.h>
#define IPC_KEY 11000
#define BUF_SIZE 128
//structure of IPC message
typedef struct msgbuf{
long mtype;
char mtext[BUF_SIZE];
} message_buf;
void handle_sigint(int sig){
signal(SIGINT,SIG_IGN);
/*
some operation to handle sigint,
here it's really simple setting
SIGINT to be ignored
*/
}
int main(){
long ipc_id;
message_buf msg;
struct sigaction setup_action;
sigset_t block_mask;
//setup sigaction for SIGINT
sigemptyset(&block_mask);
sigaddset(&block_mask,SIGINT);
setup_action.sa_handler = handle_sigint;
setup_action.sa_mask = block_mask;
setup_action.sa_flags = SA_RESTART;
if (sigaction(SIGINT, &setup_action, 0) < 0){
perror("sigaction");
exit(1);
}
//creating the ipc queue
if ((ipc_id = msgget(IPC_KEY, IPC_CREAT | IPC_EXCL | 0666))<0){
perror("error in msgget");
exit(1);
}
for(;;){
if (msgrcv(ipc_id,&msg,BUF_SIZE,1,0)<0){
perror("error in msgrcv");
exit(1);
}
printf("received message : %s\n",msg.mtext);
}
}
这是清理IPC队列的简单程序:
And here is simple program to clean up the IPC queue :
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/msg.h>
#define IPC_KEY 11000
int main(){
long ipc_id;
if ((ipc_id = msgget(IPC_KEY, IPC_CREAT | 0666 )) < 0) {
perror("error in msgget");
exit(1);
}
if (msgctl(ipc_id, IPC_RMID, 0) != 0){
perror("error in msgctl");
exit(1);
}
return 0;
}
在此先感谢您的帮助!我真的希望我不会重复提出问题,但我试图寻找一会儿解决方案,但不幸的是,除了使用if函数明确捕获EINTR errno外,没有找到其他任何东西.
Thanks in advance for help! I really hope I didn't make duplicate question but I tried to look for a while for a solution and unfortunately didn't find any other than explicitly catching EINTR errno with if function.