我的使用 IPC 队列在线程之间通信的代码有问题。
我需要安全地处理 SIGINT - 让程序在关闭之前出现 SIGINT 时完成所有活动线程。不过,我在寻找解决方案方面遇到了严重的问题,因为即使使用带有标志 SA_RESTART 的 SIGINT sigaction,msgrcv 函数也会出现 EINTR 错误。
我的问题是 - 除了 msgrcv 函数之外,还有什么方法可以避免 EINTR
在某些“if”中指定错误条件,例如:
if (msgrcv<0){
if (errno == EINTR){
errno = 0;
}
}
这是我的程序的真正简化版本,用于演示问题:
#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 队列的简单程序:
#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 之外没有找到任何其他解决方案。