Reputation: 77
I'm trying to use IPC message queue with a forked process, passing a pointer to a dynamically allocated string, but it doesn't work.
This is a simple test that I made. It doesn't print the string received from the queue. But if I try to remove the fork()
it works perfectly.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MSGSZ 128
typedef struct msgbuf {
long mtype;
char *mtext;
} message_buf;
int
main ()
{
int msqid;
char *p;
key_t key = 129;
message_buf sbuf, rbuf;
p = (char *) malloc(sizeof(char) * MSGSZ);
if ((msqid = msgget(key, IPC_CREAT|0666)) < 0) {
perror("msgget");
exit(1);
}
if (fork() == 0) {
strcpy(p, "Did you get this?");
sbuf.mtype = 1;
sbuf.mtext = p;
if (msgsnd(msqid, &sbuf, MSGSZ, IPC_NOWAIT) < 0) {
perror("msgsnd");
exit(1);
}
}
else {
sleep(1);
if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0) {
perror("msgrcv");
exit(1);
}
printf("Forked version: %s\n", rbuf.mtext);
msgctl(msqid, IPC_RMID, NULL);
}
}
Upvotes: 4
Views: 874
Reputation: 14046
The problem is that you are sending a pointer across process boundaries. Pointers are only valid within the same process and are meaningless when sent/used in another process. In fact, you are sending the pointer value followed by a whole bunch of garbage bytes as themsgbuf.mtext
is in fact not MSGSZ
bytes in size (so technically invoking Undefined Behaviour).
What you need to do is to declare the buffer inline in the message. That is, change the message_buf
definition to be:
typedef struct msgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;
And then strcpy straight into mtext
:
strcpy(sbuf.mtext, "Did you get this?");
For clarity, below is the full program with the changes described:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MSGSZ 128
typedef struct msgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;
int
main (void)
{
int msqid;
key_t key = 129;
message_buf sbuf, rbuf;
if ((msqid = msgget(key, IPC_CREAT|0666)) < 0) {
perror("msgget");
exit(1);
}
if (fork() == 0) {
strcpy(sbuf.mtext, "Did you get this?");
sbuf.mtype = 1;
if (msgsnd(msqid, &sbuf, MSGSZ, IPC_NOWAIT) < 0) {
perror("msgsnd");
exit(1);
}
}
else {
sleep(1);
if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0) {
perror("msgrcv");
exit(1);
}
printf("Forked version: %s\n", rbuf.mtext);
msgctl(msqid, IPC_RMID, NULL);
}
}
Upvotes: 3