C - Problem with message passing between threads using queues

11,610

Solution 1

Edit: The sizeof(struct msg) - offsetof(struct msg, numResources); should be ok.

But, your mtype needs to be, as per the docs, a positive integer. Initialize it to 2, as your calls to msgrecv says to receive only message type 2.

Add error checking to all the msgsnd/msgrecv calls , so you're sure you're not silently getting errors.

Add error checking to your ftok and msgget calls.

Solution 2

Your problem is that you have set nonsense permissions on your message queues. In these lines, you have used a decimal constant 666 where you should have used an octal constant 0666:

    msqid1 = msgget(key1, 666 | IPC_CREAT);
    msqid1 = msgget(key1, 666 | IPC_CREAT);

This means that you've created the queues with octal permissions 01232, which doesn't include read permission - so your subsequent msgget() calls are all now failing with EPERM (which you'll see if you check those calls for errors).

You will have to remove your message queues and allow your program to re-create them with the correct permissions. You need to use the msqid for the queue with the IPC_RMID command to msgctl() to do this, as in the following program:

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

int main(int argc, char *argv[])
{
        if (argc < 2) {
                fprintf(stderr, "Usage: %s <msqid> [<msgqid> ...]\n", argv[0]);
                return 1;
        }

        while (*++argv)
        {
                int msqid = atoi(*argv);

                printf("Removing msqid %d\n", msqid);
                if (msgctl(msqid, IPC_RMID, NULL) != 0) {
                        perror("msgctl");
                        return 2;
                }
        }

        return 0;
}

Due to the awful design of SYS V message queues, you can't get the msqid values from msgget() anymore, because msgget() fails. To get the msqid values to remove, look in the file /proc/sysvipc/msg.

PS:

I highly recommend using POSIX message queues instead (mq_open(), mq_send(), mq_receive() etc.). The interface is significantly improved.

Solution 3

Here's what it printed on the run that appeared to work.

program starting
Msg sent from client

*****In client thread*****
Msg received by client
received: numResources requested = 0
sending: numResources requested = 1
Msg sent from client


*****In server thread*****
Msg received by server
received: numResources requested = 1
sending: numResources requested = 9001
Msg sent from server.


*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client


*****In server thread*****
Msg received by server
received: numResources requested = 9002
sending: numResources requested = 9001
Msg sent from server.


*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client


*****In server thread*****
Msg received by server
received: numResources requested = 9002
sending: numResources requested = 9001
Msg sent from server.


*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client

And immediately after....

program starting
Msg sent from client

*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client


*****In server thread*****
Msg received by server
received: numResources requested = 0
sending: numResources requested = 9001
Msg sent from server.


*****In client thread*****
Msg received by client
received: numResources requested = 9002
sending: numResources requested = 9003
Msg sent from client


*****In server thread*****
Msg received by server
received: numResources requested = 9001
sending: numResources requested = 9001
Msg sent from server.


*****In client thread*****
Msg received by client
received: numResources requested = 9003
sending: numResources requested = 9004
Msg sent from client


*****In server thread*****
Msg received by server
received: numResources requested = 9001
sending: numResources requested = 9001
Msg sent from server.

These were run 1 after the other with no changes made to the code in between.

Share:
11,610
Anon
Author by

Anon

Updated on June 04, 2022

Comments

  • Anon
    Anon almost 2 years

    I'm trying to pass messages between 2 threads using a queue, but I haven't gotten any results so far. When I print the contents of the message after it's received and before it's sent, it only seems to keep its value within the tread. I need to implement it with 1 server thread and multiple client threads, but for now I'm only using 1 of each. Here's my code

    struct msg                                //struct for client requests to server
    {
            long mtype;
            int numResources;           //number of resources to be requested
            int ID;                     //ID associated with client thread
    };                                         
    
    int c1PID;                              //process ID variable for client thread 1
    int serverPID;
    
    key_t key1;
    key_t keyS;
    
    int msqid1;
    int msqidS;
    
    int main(int arc, char *argv[])
    {
            key1 = ftok(".", '1');      //queue for client thread 1 to receive msgs from server
            msqid1 = msgget(key1, 666 | IPC_CREAT);
    
            keyS = ftok(".", 's');                          //general queue for server
            msqidS = msgget(keyS, 666 | IPC_CREAT);
    
            pthread_t threads[2];              //create an array of pthreads
    
            if ((serverPID = pthread_create(&threads[0], NULL, server, NULL)) != 0)
            {
                    perror("server thread");
                    exit(1);
            }
    
            if ((c1PID = pthread_create(&threads[1], NULL, client, NULL)) != 0)
            {
                    perror("client thread");
                    exit(1);
            }
    
            pthread_exit(NULL);
    }
    
    void *server()
    {                                  
            struct msg request;
            size_t size = sizeof(struct msg) - offsetof(struct msg, numResources);
    
            while (1)
            {
    
                    msgrcv(msqidS, &request, size, 2, 0);
    
                    printf("received: numResources requested = %d\n", request.numResources);
    
                    request.numResources = 9001;
    
                    printf("sending: numResources requested = %d\n", request.numResources);
    
                    msgsnd(msqid1, &request, size, 0);
    
                    sleep(1);
            }
    }
    
    void *client()
    {
            struct msg request;
            size_t size;
            request.numResources = 0;
            size = sizeof(struct msg) - offsetof(struct msg, numResources);
    
            msgsnd(msqidS, &request, size, 0);
    
            while(1)
            {
                    msgrcv(msqid1, &request, size, 2, 0);
    
                    printf("received: numResources requested = %d\n", request.numResources);
    
                    request.numResources += 1;//(int)(ceil((double)(rand()%2)) + 1);
    
                    printf("sending: numResources requested = %d\n", request.numResources);
    
                    msgsnd(msqidS, &request, size, 0);
    
                    sleep(1);
    }
    

    I took out a lot of my print statements, but it looks something like this:

    Server thread: 
    received: numResources = 9001;
    sending: numResources = 9001;
    
    client thread:
    received: numResources = 1;
    sending: numResources = 2;
    
    Server thread: 
    received: numResources = 9001;
    sending: numResources = 9001;
    
    client thread:
    received: numResources = 2;
    sending: numResources = 3;