Unix Programming - msqrcv strangeness

This is Interesting: Free IT Magazines  
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!

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com