I'm trying to send a 1KB string over a message queue between a parent process and its forked child. Unfortunately, my calls to msgsnd
, msgrcv
, etc. are suddenly all returning -1 and causing the EINVAL
error.
I found that this error (in the case of msgsnd
, for example) occurs when msqid
is invalid, the message type argument is set at <1, or the msgsz
is out of range. But upon testing, as far as I can tell, msgget
is returning a perfectly valid ID number and the type is set fine. There must be a problem with my buffer ranges, but I thought I set them up correctly. In the code, I have added comments to explain (sorry about all of the frantically-added #includes):
#include <errno.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cstring>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sstream>
#define PERMS (S_IRUSR | S_IWUSR)
#define NUMBYTES 1024 //number of chars (bytes) to be sent
using namespace std;
//Special structure for messages
typedef struct {
long mtype;
char mtext[NUMBYTES];
} mymsg_t;
int main(){
//Construct a generic test message of the specified size
char message[NUMBYTES];
for(int i = 0; i < NUMBYTES; i++)
message[i] = 'a';
//Create the message queue (accessed by both parent
//and child processes)
int msqid;
int len;
if(msqid = msgget(IPC_PRIVATE, PERMS) == -1)
perror("Failed to create new message queue!\n");
if(fork() == 0){ //Child process...does the sending
mymsg_t* mbuf;
len = sizeof(mymsg_t) + strlen(message); //doesn't work with " + sizeof(message)" either
void* space;
if((space = malloc(len)) == NULL) //this works fine; no error output
perror("Failed to allocate buffer for message queue.\n");
mbuf = (mymsg_t*)space;
strcpy(mbuf->mtext, message);
mbuf->mtype = 1; //a default
//Some error checks I tried...
//cout<<"msqid is " << msqid << endl;
//cout << "mbuf ptr size is " << sizeof(mbuf) << ". And this non-ptr: "<<sizeof(*mbuf)<<". And
//len: "<<len<<endl;
if(msgsnd(msqid, mbuf, len+1, 0) == -1)
perror("Failed to send message.\n"); //this error occurs every time!
free(mbuf);
}
else{ //Parent process...does the receiving
usleep(10000); //Let the message come
mymsg_t mymsg; //buffer to hold message
int size;
if((size = msgrcv(msqid, &mymsg, len+1, 0, 0)) == -1) //error every time
perror("Failed to read message queue.\n");
//checking that it made it
//cout << "Hopefully printing it now? : " << endl;
//if(write(STDOUT_FILENO, mymsg.mtext, size) == -1)
// perror("Failed to write to standard output!\n");
}
ostringstream oss;
oss << "ipcrm -q " << msqid;
string command = oss.str();
if(system(command.c_str()) != 0) //also errors every time, but not main focus here
perror("Failed to clean up message queue!");
}
What is going on here? I thought I had the buffer procedure working fine and with sufficient space..