msgrcv-SA_RESTART标志不起作用 [英] msgrcv - SA_RESTART flag doesn't work

查看:160
本文介绍了msgrcv-SA_RESTART标志不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码有问题,该代码使用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.

推荐答案

来自

以下接口在中断后再也不会重启 通过信号处理程序,无论使用SA_RESTART为何;他们总是 被信号中断时失败,并显示错误EINTR 处理程序:

The following interfaces are never restarted after being interrupted by a signal handler, regardless of the use of SA_RESTART; they always fail with the error EINTR when interrupted by a signal handler:

....

  • 系统V IPC接口: msgrcv(2) ,msgsnd(2),semop(2)和semtimedop(2).

SA_RESTART的处理方式是定义的位实现.您没有使用特定的Unix风格进行标记,但是我认为您的Unix根本就不遵守SA_RESTART的特定系统调用要求.

The way SA_RESTART is handled is a bit implementation defined. You didn't tag with a specific Unix flavor but I assume your Unix simply doesn't obey SA_RESTART for your specific system call.

这篇关于msgrcv-SA_RESTART标志不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆