开发者

Error in msgrcv: Invalid Arguments

I am writing a code in C on a unix system. I have created a message queue server. Each time I receive a new message I fork and the child process handles the new client. The server waits for new client. Here's the code.

for (;;)
 {
      struct my_msgbuf buf;

      if (msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0) == -1)
      perror ("msgrcv");


    if((pid = fork())<0)
    perror("fork");


    if开发者_如何转开发(pid==0)
    {
     //child code
    }
}

Now the code works for the first iteration but on the second iteration msgrcv gives the following error - msgrcv: Invalid Arguments instead of waiting for new messages.


msgrcv does take a msgsz parameter, but it's not the size of a struct my_msgbuf, rather, it's the number of bytes in the mtext[] field of the structure.

You aren't really supposed to use struct msgbuf directly, I think. It would be normal to define your own with appropriate space. The way you have it, your buf declaration allocates only 1 byte, and then the code tells the kernel that you have sizeof buf bytes, which you don't. As a result, the code is said to invoke Undefined Behavior or UB.

This may or may not explain the EINVAL but one should always fix the known bugs and retest because UB taints further analysis...


There are few issues with the above code. Firstly here

msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0)

second argument &(buf.mtype) is incorrect as process is expected to receive complete buf not only buf.mtype. If struct my_msgbuf looks like

struct my_msgbuf {
       long mtype;       /* message type, must be > 0 */
       char mtext[1];    /* message data */

};

then msgrcv() should look like

msgrcv (msqid, &buf, sizeof(buf), 1, 0);

Now the code works for the first iteration but on the second iteration msgrcv gives the following error - msgrcv: Invalid Arguments instead of waiting for new messages ?

That's because msgrcv() executes before fork(), what if parent process doesn't executes msgsnd() ?

To resolve this you should keep msgrcv() statement inside child process. Also run the for loop inside child & parent process not outside child/parent block. For e.g

struct my_msgbuf buf;

if((pid = fork())<0)
{
    /* @TODO set the buf.mtype here  */
    perror("fork");
    for(;;) /* use loop inside parent process to write into MQ continuously */
    {
        /* @TODO scan the data into  buf.mtext */
        /* @TODO msgsnd statement */
    }
}
else
{
    for(;;) /* use loop inside child process to read from MQ continuously */
    {
        if (msgrcv (msqid, &buf, sizeof (buf), 1, 0) == -1)
            perror ("msgrcv");
        printf("received data : %s\n", buf.mtext);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜