我正在编写一个程序,它应该像服务器一样工作,并不断地从消息队列中读取并处理接收到的消息。
主循环如下所示:
while (1) {
/* Receive message */
if (msgrcv(msqid, &msg, sizeof(struct msgbuffer) - sizeof(long), 0, 0) == -1) {
perror("msgrcv");
exit(1);
}
//more code here
}我遇到的问题是,如果不依赖客户机向服务器发送一条指示应该停止的消息,我就无法找到一种体面地退出这个循环的方法。我在循环之后做了很多资源清理,而我的代码永远无法到达那个点,因为循环不会结束。
我试着做的一件事就是听一个SIGINT来结束循环.
volatile sig_atomic_t stop;
void end(int signum) {
stop = 1;
}
int main(int argc, char* argv[]) {
signal(SIGINT, end);
//some code
while (!stop) {
/* Receive message */
if (msgrcv(msqid, &msg, sizeof(struct msgbuffer) - sizeof(long), 0, 0) == -1) {
perror("msgrcv");
exit(1);
}
//more code here
}
//cleanup
}...but,因为循环挂在系统调用本身上,这不起作用,只会导致perror打印出msgrcv: Interrupted system call,而不是终止循环和清理我的资源。
有什么方法可以终止系统调用并优雅地退出循环?
解决方案:
多亏了利维美,我才能解决我的问题。以下是我为使它发挥作用所做的工作:
volatile sig_atomic_t stop;
void end(int signum) {
stop = 1;
}
int main(int argc, char* argv[]) {
signal(SIGINT, end);
//some code
while (!stop) {
/* Receive message */
if (msgrcv(msqid, &msg, sizeof(struct msgbuffer) - sizeof(long), 0, 0) == -1) {
if (errno == EINTR) break;
else {
perror("msgrcv");
exit(1);
}
}
//more code here
}
//I can now reach this code segment
}发布于 2015-03-25 00:50:58
你最好看看现有的软件,它是一种非常常见的模式,不像你希望的那么简单。然而,基本要素是:
对于一个非平凡的程序,你会更好地使用这个“毒药”的方法来杀死循环。用msgsend给自己发一条消息说杀了我。这样,你就能得到可预见的结果。
鲁思
发布于 2015-03-25 04:59:06
the code could have the following implemented:
have the msgflg parameter contain 'IPC_NOWAIT'
then, the next line in the code should check 'errno'
for the value 'EAGIN'
when errno is EAGIN, either loop to recall msgrcv() or exit
the loop due to some other criteria.
optionally the code could nanosleep() for a while
before jumping back to the top of the loop
extracted from the man page for msgrcv()
"EAGAIN No message was available in the queue
and IPC_NOWAIT was specified in msgflg."https://stackoverflow.com/questions/29245596
复制相似问题