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);
}
}
精彩评论