0

I need some help with msgrcv... I need to be able to receive messages like this:

while(1){
    int status = msgrcv(qid, &msg, sizeof(msg.data), user_id,0 )
    if(status < 0) { perror("something wrong..."); exit(1); }
}

And also somewhere on the code:

void stuff_to_do(int signal){
   //   ....
}
//...
signal(SIGQUIT, stuff_to_do);

But I get a Interrupted System Call, probably because the signal kills the msgrcv or something like that. How can I solve this? Should i fork() and do the msgrcv in one process and do the stuff on the other process? Or is there a better way? Thanks for the help!

David Frickert
  • 127
  • 2
  • 10
  • Don't try to `fork()` and divide the tasks, that would just complicate things. Whatever process that calls `msgrcv()` can still receive signals and get interrupted. – e0k Dec 10 '16 at 03:38
  • @e0k Yes that's true... I thought it would solve it but it won't since I need to stop the while ( 1 ) with a signal. Thanks! – David Frickert Dec 10 '16 at 03:42

1 Answers1

1

Yes, if your process receives a signal during msgrcv(), it will be interrupted.

From the man pages on msgrcv():

The calling process catches a signal. In this case the system call fails with errno set to EINTR. (msgrcv() is never automatically restarted after being interrupted by a signal handler, regardless of the setting of the SA_RESTART flag when establishing a signal handler.)

Try to identify this failure condition and just restart msgrcv() with something like

while (1) {
    // Try to receive message
    errno = 0;
    int status = msgrcv(qid, &msg, sizeof(msg.data), user_id,0 )

    if (status < 0) {
        if (errno == EINTR) continue;  // try again

        // Something else went wrong
        perror("something wrong...");
        exit(1);
    }
}

Don't forget that you have to manually set errno = 0 before the operation you want to test.

This reminds me of a good answer that describes concurrency and simultaneity. It explains why you have to always use the approach of trying the operation, then check to see if it succeeded.


See also:

Community
  • 1
  • 1
e0k
  • 6,961
  • 2
  • 23
  • 30