Reputation: 4840
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
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