|
Home > Archive > Unix Programming > August 2006 > msqrcv strangeness
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
msqrcv strangeness
|
|
| quigstah@gmail.com 2006-08-25, 1:26 pm |
| Hey Folks:
I'm seeing some unexpected behavior in a small bit of trivial sysv
message queue code. I send to the queue without issue, but when I
attempt to read, I can only pop one item off the queue before I receive
the following error:
msgrcv: Invalid argument
Here are the relevant code blocks:
// SEND
while(1)
{
fprintf(stdout, "mqueue> ");
if(fgets(msqdata.buf, sizeof(msqdata.buf), stdin) == NULL)
break;
msgsnd(msqid, &msqdata, sizeof(msqdata), 0);
}
// RECEIVE
while(1)
{
if(msgrcv(msqid, &msqdata, sizeof(msqdata), 0, 0) == -1)
{
perror("msgrcv");
exit(1);
}
fprintf(stdout, "received: %s\n", msqdata.buf);
}
These two snippets of code are located in different apps that run in
parallel.
Any insight as to why I can't pull more than one message from the queue
would be much appreciated. My thanks in advance.
- John
| |
| quigstah@gmail.com 2006-08-25, 1:26 pm |
| Folks:
As a quick addendum, I should add that if I modify the RECEIVE code,
everything works as you'd expect:
while(1)
{
msqid = msgget(key, 0644); /* FIX */
if(msgrcv(msqid, &msqdata, sizeof(msqdata), 0, 0) == -1)
{
perror("msgrcv");
exit(1);
}
fprintf(stdout, "received: %s\n", msqdata.buf);
}
So, I guess the question is, more precisely, why does this app get
disconnected from the queue upon each receive?
- John
| |
| Nils O. Selåsdal 2006-08-25, 1:26 pm |
| quigstah@gmail.com wrote:
> Hey Folks:
>
> I'm seeing some unexpected behavior in a small bit of trivial sysv
> message queue code. I send to the queue without issue, but when I
> attempt to read, I can only pop one item off the queue before I receive
> the following error:
>
> msgrcv: Invalid argument
>
> Here are the relevant code blocks:
>
> // SEND
>
> while(1)
> {
> fprintf(stdout, "mqueue> ");
>
> if(fgets(msqdata.buf, sizeof(msqdata.buf), stdin) == NULL)
> break;
>
> msgsnd(msqid, &msqdata, sizeof(msqdata), 0);
> }
>
> // RECEIVE
>
> while(1)
> {
> if(msgrcv(msqid, &msqdata, sizeof(msqdata), 0, 0) == -1)
> {
> perror("msgrcv");
> exit(1);
> }
> fprintf(stdout, "received: %s\n", msqdata.buf);
> }
>
> These two snippets of code are located in different apps that run in
> parallel.
>
> Any insight as to why I can't pull more than one message from the queue
> would be much appreciated. My thanks in advance.
Perhaps you have a buffer overflow somewhere.
Could you post a complete compilable example ?
| |
| quigstah@gmail.com 2006-08-25, 7:28 pm |
| Nils:
> Perhaps you have a buffer overflow somewhere.
> Could you post a complete compilable example ?
Absolutely, thanks for taking a look.
------- sysv-write.c
---------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#define BUF 128
int strip_newline ( char *msg, int msg_size );
typedef struct msqdata {
long mtype;
char mtext[BUF];
} msqdata_t;
int main ( int argc, char **argv )
{
int idx = 1;
int msqid;
key_t key;
msqdata_t msqdata;
// open the message queue
key = ftok(".", '-');
msqid = msgget(key, 0666 | IPC_CREAT);
msqdata.mtype = 1;
while(1)
{
fprintf(stdout, "mqueue[%d]> ", idx++);
if(fgets(msqdata.mtext, sizeof(msqdata.mtext), stdin) == NULL)
break;
strip_newline(msqdata.mtext, sizeof(msqdata.mtext));
if(strcmp(msqdata.mtext, "exit") == 0)
break;
fprintf(stdout, "sending: %s\n", msqdata.mtext);
msgsnd(msqid, &msqdata, sizeof(msqdata), 0);
}
msgctl(msqid, IPC_RMID, NULL);
fprintf(stdout, "Quit.\n");
return EXIT_SUCCESS;
}
int strip_newline ( char *msg, int msg_size )
{
int idx;
for(idx = 0; idx < msg_size; idx++)
{
if(msg[idx] == '\n')
{
msg[idx] = '\0';
break;
}
}
return 1;
}
----- sysv-read.c
------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#define BUF 128
typedef struct msqdata {
long mtype;
char mtext[BUF];
} msqdata_t;
int main ( int argc, char **argv )
{
int msqid;
key_t key;
msqdata_t msqdata;
// open the message queue
key = ftok(".", '-');
msqid = msgget(key, 0644);
while(1)
{
if(msgrcv(msqid, &msqdata, sizeof(msqdata), 0, 0) == -1)
{
perror("msgrcv");
exit(1);
}
fprintf(stdout, "received: %s\n", msqdata.mtext);
}
fprintf(stdout, "Quit.\n");
return EXIT_SUCCESS;
}
| |
| David Schwartz 2006-08-25, 7:28 pm |
|
quigstah@gmail.com wrote:
Let's see what your code does.
> int main ( int argc, char **argv )
> {
> int msqid;
> key_t key;
> msqdata_t msqdata;
> // open the message queue
> key = ftok(".", '-');
> msqid = msgget(key, 0644);
You get the values of 'key' and 'msqid'.
> while(1)
> {
> if(msgrcv(msqid, &msqdata, sizeof(msqdata), 0, 0) == -1)
Then you overflow 'msqdata', corrupting the value of 'msqid'!
Read the documentation for 'msgrcv'. The length is the length of the
message, not the structure containing it.
Your sender has the same problem.
DS
| |
| quigstah@gmail.com 2006-08-25, 7:28 pm |
| David:
> Then you overflow 'msqdata', corrupting the value of 'msqid'!
You caught it, thanks so much!
|
|
|
|
|