user
user

Reputation: 4840

C IPC - cannot receive message from queue

I wrote a simple program in C that uses IPC message queues, but I cannot receive a message when I send it as pointer.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <ctype.h>
#include <string.h>

typedef struct Message {
    long type;
    char content[16];
} Message;

int main(int argc, char* argv[]) {

    printf("Starting...\n");
    key_t key = 1;
    Message* msg = malloc(sizeof(Message));
    int msg_id = msgget(key, IPC_CREAT | 0777);
    printf("ID of the created queue: %d\n", msg_id);
    strcpy(msg->content, "Hello");
    msgsnd(msg_id, msg, 16, 0);
    free(msg);

    if (fork() == 0) {
        int msgid = msgget(key, 0);
        printf("Message queue id: %d\n", msgid);
        Message rcvMsg;
        msgrcv(msgid, &rcvMsg, 16, 0, 0);
        printf("Received: %s\n", rcvMsg.content);

        if (msgctl(msgid, IPC_RMID, 0) != 0) {
            perror("Cannot remove queue from system.\n");
            exit(1);
        }

        exit(0);
    }

    wait(NULL);
    printf("Stop.\n");
    exit(0);
}

Output which I got is:

Starting... ID of the created queue: 327680 Message queue id: 327680

And program is waiting. But when I send a message as standard variable - not a pointer to structure - the message is delivered.

Working program:

int main(int argc, char* argv[]) {

    printf("Starting...\n");
    key_t key = 1;
    Message msg;
    int msg_id = msgget(key, IPC_CREAT | 0777);
    printf("ID of the created queue: %d\n", msg_id);
    strcpy(msg.content, "Hello");
    msgsnd(msg_id, &msg, 16, 0);

    if (fork() == 0) {
        int msgid = msgget(key, 0);
        printf("Message queue id: %d\n", msgid);
        Message rcvMsg;
        msgrcv(msgid, &rcvMsg, 16, 0, 0);
        printf("Received: %s\n", rcvMsg.content);

        if (msgctl(msgid, IPC_RMID, 0) != 0) {
            perror("Cannot remove queue from system.\n");
            exit(1);
        }

        exit(0);
    }

    wait(NULL);
    printf("Stop.\n");
    exit(0);
}

And this program returns expected output:

Starting... ID of the created queue: 327680 Message queue id: 327680 Received: Hello Stop.

What's going on? What is wrong? How to debug it?

And one more question is what is the best way to create structure variables - pointer or not pointer (btw. what is the name of not pointer variables of structure?)?

Message msg; or Message* msg = malloc(sizeof(Message));

Upvotes: 1

Views: 1746

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 224312

You did not initialize the type field of the message. msgsnd requires that the type field has a positive integer value.

You should change the code so that it examines the return value of every function with a return value. I found this error by changing msgsnd(msg_id, msg, 16, 0); to int result = msgsnd(msg_id, msg, 16, 0); and then inserting:

if (result == -1)
{
    perror("msgsnd");
    exit(EXIT_FAILURE);
}

This told me that msgsnd had an invalid argument, so I reviewed its documentation and found that type had to be positive.

You should also examine the return values of msgrcv.

For small structures like this, there is no need to malloc unless you need the structure to continue to exist after the function that creates it exits. If a function is just going to use a message structure and discard it, declare it locally. If the function is going to return a message structure to its caller, allocate it with malloc and return a pointer. (Then the caller is responsible for freeing it later by passing its pointer to free.)

Upvotes: 4

Related Questions