LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Message queue items not being removed (https://www.linuxquestions.org/questions/programming-9/message-queue-items-not-being-removed-738024/)

sd9 07-06-2009 05:41 AM

Message queue items not being removed
 
I've tried adding items to a message queue, and it works.
When I tried to remove it, it does not remove it.
The code I've used is given below. Isn't msgrcv() supposed to remove the items from the queue?
Code:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

main()
{
        key_t key;
        int msqid=0;
        int pmb=934,inp=0,reply=1;

        printf("Add to queue? [1=y/0=n]\n");
        scanf("%d",&reply);

        if (reply==1)
        {
                key = ftok("/home/beej/somefile", 'b');
                msqid = msgget(key, 0666 | IPC_CREAT);
                msgsnd(msqid, &pmb, sizeof(pmb), 0);  /* put it onto the queue */

                //printf("\nJust a sec...\n");
                //scanf("%d",&inp);
        }
        printf("Removing it from queue\n");

        /*-----------get it off the queue-----------*/

        key = ftok("/home/beej/somefile", 'b');
        msqid = msgget(key, 0666 | IPC_CREAT);

        msgrcv(msqid, &pmb, sizeof(pmb), 2, 0);  /* get it off the queue */


}/*main*/


pixellany 07-08-2009 08:14 AM

Moved: This thread is more suitable in <Programming> and has been moved accordingly to help your thread/question get the exposure it deserves.

theNbomr 07-08-2009 10:04 AM

When you write a message, part of that message is the message type. Ordinarily, one uses as the message, a struct, with the first element being the long int mtype field, followed by the message payload. This field must agree with the mtype parameter (4th param) in the call to msgrcv().
You seem to be using Beej's Guide (good), so go back and read more carefully.

--- rod.

dwhitney67 07-08-2009 10:10 AM

I agree. Another good source of information is the man-pages.

I threw this little program together using the information I gathered (from the man-page):
Code:

#include <sys/msg.h>
#include <stdio.h>
#include <assert.h>


/* user defined data structure */
struct Data
{
  int value;
};

const unsigned int DATA_TYPE = 5;

/* user defined Message Queue data transport buffer */
struct MsgBuf
{
  long        mtype;
  struct Data data;
};


int main()
{
  key_t  key  = ftok("somefile", 'b');
  int    msqid = msgget(key, 0666 | IPC_CREAT);
  struct MsgBuf msg;
  struct MsgBuf rcvmsg;

  /* prepare message transport buffer that will be sent */
  msg.mtype      = DATA_TYPE;
  msg.data.value = 123;

  /* send the transport buffer */
  printf("Writing to the queue...\n");
  assert(msgsnd(msqid, &msg, sizeof(msg), 0) == 0);

  /* receive the transport buffer */
  printf("Removing from queue...\n");
  assert(msgrcv(msqid, &rcvmsg, sizeof(rcvmsg), DATA_TYPE, 0) == sizeof(struct MsgBuf));

  printf("value = %d\n", rcvmsg.data.value);

  return 0;
}

I don't know if I did it correctly, that is, with respect to the MsgBuf struct I created, but the program does send and receive the data.

sd9 07-09-2009 05:49 AM

Quote:

Originally Posted by dwhitney67 (Post 3601027)
I agree. Another good source of information is the man-pages.

I threw this little program together using the information I gathered (from the man-page):
Code:

#include <sys/msg.h>
#include <stdio.h>
#include <assert.h>


/* user defined data structure */
struct Data
{
  int value;
};

const unsigned int DATA_TYPE = 5;

/* user defined Message Queue data transport buffer */
struct MsgBuf
{
  long        mtype;
  struct Data data;
};


int main()
{
  key_t  key  = ftok("somefile", 'b');
  int    msqid = msgget(key, 0666 | IPC_CREAT);
  struct MsgBuf msg;
  struct MsgBuf rcvmsg;

  /* prepare message transport buffer that will be sent */
  msg.mtype      = DATA_TYPE;
  msg.data.value = 123;

  /* send the transport buffer */
  printf("Writing to the queue...\n");
  assert(msgsnd(msqid, &msg, sizeof(msg), 0) == 0);

  /* receive the transport buffer */
  printf("Removing from queue...\n");
  assert(msgrcv(msqid, &rcvmsg, sizeof(rcvmsg), DATA_TYPE, 0) == sizeof(struct MsgBuf));

  printf("value = %d\n", rcvmsg.data.value);

  return 0;
}

I don't know if I did it correctly, that is, with respect to the MsgBuf struct I created, but the program does send and receive the data.

Yay! I've done it at last. Thanks dwhitney67 :)
I referred your code and was able to make corrections in mine. Took a long time though...
Corrected code:
Code:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

main()
{
        key_t key;
        int msqid=0;
        int pmb=934,inp=0,reply=1;

        printf("Add to queue? [1=y]\n");
        scanf("%d",&reply);

        if (reply==1)
        {
                key = ftok("/home/beej/somefile", 'b');
                msqid = msgget(key, 0666 | IPC_CREAT);
                msgsnd(msqid, &pmb, sizeof(pmb), 0);  /* put it onto the queue */

                //printf("\nJust a sec...\n");
                //scanf("%d",&inp);

                printf("Remove from queue? [1=y]");
                scanf("%d",&reply);
                if (reply==1)
                {
                        printf("Removing it from queue\n");

                        /*-----------get it off the queue-----------*/
                        //key = ftok("/home/beej/somefile", 'b');
                        //msqid = msgget(key, 0666 | IPC_CREAT);
                        msgrcv(msqid, &pmb, sizeof(pmb), 0, 0);  /* get it off the queue */
                }//if
        }//if


}/*main*/


theNbomr 07-09-2009 09:24 AM

Just a couple of comments...
In many/most cases, the queue will be used by multiple processes, as distinct from your example code, where the producer and consumer are in a single process, and share the same queue ID variable. So, all processes will have to open a message queue, and acquire their own message queue IDs. Each process can open the queue with different permissions, as appropriate.
Along the same lines, again in most cases, the consumer will expect that the queue already exists, and not use the O_CREAT flag to open the queue. If this flag is not used, the msgget() call will fail, and return -1, which the caller can use to detect that there is probably no producer process, and act accordingly. The key returned by ftok() will probably be -1, if the path argument is a pathname of a non-existant file (as I suspect is the case in your example code). You should check the return values from these two functions, and take the appropriate branch as necessary.
There exists the handy tool ipcs, for examining and managing the state of queues and other IPC methods on a host.
--- rod.

dwhitney67 07-09-2009 09:37 AM

Thanks for the info theNbomr. I just remembered that one thing I forgot to do in my sample program was to remove the message queue once I was done with it. This was quite apparent when I ran "ipcs".

@ the OP:

Make sure you insert this call when you are done using your message queue:
Code:

...

msgctl(msqid, IPC_RMID, 0);


sd9 07-09-2009 11:20 PM

Quote:

Originally Posted by theNbomr (Post 3602249)
Just a couple of comments...

Thanks for posting....there's also the ipcrm tool which comes in handy.


@dwhitney67: Thanks for the msgctl(). Needed that one too. Works like a charm! :)

Code:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

main()
{
        key_t key;
        int msqid=0;
        int pmb=934,inp=0,reply=1;

        printf("Add to queue? [1=y]\n");
        scanf("%d",&reply);

        if (reply==1)
        {
                key = ftok("/home/beej/somefile", 'b');
                msqid = msgget(key, 0666 | IPC_CREAT);
                msgsnd(msqid, &pmb, sizeof(pmb), 0);  /* put it onto the queue */

                //printf("\nJust a sec...\n");
                //scanf("%d",&inp);

                printf("Remove from queue? [1=y]");
                scanf("%d",&reply);
                if (reply==1)
                {
                        printf("Removing it from queue\n");

                        /*-----------get it off the queue-----------*/
                        //key = ftok("/home/beej/somefile", 'b');
                        //msqid = msgget(key, 0666 | IPC_CREAT);
                        msgrcv(msqid, &pmb, sizeof(pmb), 0, 0);  /* get it off the queue */
                }//if

                printf("Delete the queue? [1=y]");
                scanf("%d",&reply);
                if (reply==1)
                {
                        msgctl(msqid, IPC_RMID, 0);
                        printf("Removed from queue");
                }
        }//if
}//main



All times are GMT -5. The time now is 11:27 PM.