I have written a program in c that creates a child process for receiving messages and the parent sends messages. It will not receive messages from its parent process, this is by design and my reason for using MSG_EXCEPT. So it is intended to have 2 instances of the program running, and they can send and receive messages. The issue is that the program only sends some messages, not all, and I have no clue why...
Also, I have to use gcc -D_GNU_SOURCE chat.c -o chat to compile, otherwise it has an error about MSG_EXCEPT. Does anyone know a better way to get MSG_EXCEPT to work without using those compiler flags? Something in code would be preferable, so that this can be portable.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
typedef struct messageBuffer {
long type;
char text[256];
} MsgBuf;
typedef struct MessageStruct {
MsgBuf message;
int success;
} Message;
void handler(int sig){
_exit(0);
}
int open_queue( key_t keyval )
{
int qid;
if((qid = msgget( keyval, IPC_CREAT | 0666 )) == -1)
{
return(-1);
}
return qid;
}
void SendMessage(int qid, int msgtype, char* msgtxt)
{
MsgBuf msg;
time_t t;
msg.type = msgtype;
snprintf(msg.text, sizeof(msg.text), "%s", msgtxt);
time(&t);
if(msgsnd(qid, (void*)&msg, sizeof(msg.text), IPC_NOWAIT) == -1)
{
perror("msgsnd error");
exit(EXIT_FAILURE);
}
}
Message ReceiveMessage(int qid, int msgtype)
{
Message msg;
msg.success = 1;
if(msgrcv(qid, (void*)&msg.message, sizeof(msg.message.text), msgtype, IPC_NOWAIT | MSG_NOERROR | MSG_EXCEPT) == -1)
{
if (errno != ENOMSG)
{
perror("msgrcv");
exit(EXIT_FAILURE);
}
else
msg.success = 0;
}
return msg;
}
void ClearCurrentConsoleLine()
{
printf("\x1b[1F"); // Move to beginning of previous line
printf("\x1b[2K"); // Clear entire line
}
int main(void)
{
pid_t pid;
pid_t ppid = getpid();
int msgkey = 6666;
char str[256];
Message msg;
char* writemsg = "Write your message below:\n";
pid = fork();
int qid = open_queue(msgkey);
if(qid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
if(pid < 0)
{
perror("Forking error!");
abort();
}
else if(pid == 0)
{
signal(SIGCONT,handler);
while(1)
{
msg = ReceiveMessage(qid, ppid);
if(msg.success)
{
ClearCurrentConsoleLine();
printf("message: %ld: %s\n", msg.message.type, msg.message.text);
printf("%s", writemsg);
}
}
exit(0);
}
while(1)
{
printf("%s", writemsg);
fgets(str, sizeof(str), stdin);
int n = strlen(str);
if(str[n-1] == '\n')
str[n-1] = '\0';
ClearCurrentConsoleLine();
ClearCurrentConsoleLine();
printf("Me: %s\n", str);
if(strcmp(str, "exit") == 0)
{
printf("exiting\n");
break;
}
SendMessage(qid, ppid, str);
}
printf("Killing: %d\n", pid);
kill(pid,SIGCONT);
exit(0);
}
MSG_EXCEPT should not be used here, just remove this flag
MSG_EXCEPT
Used with msgtyp greater than 0 to read the first message
in the queue with message type that differs from msgtyp.
Turns out there was just an issue with that specific message queue. So I just closed the message queue and started a new one and all fixed. In regards to the MSG_EXCEPT, I need to use that because I don't want to just get any message currently in the queue, as I would with 0, I want to get any message that is not submitted by myself, any message except one with the key that I am using to send them. Another way I could do this would be to have 2 message queues per process, one for acquiring the key and message queue of another chat process, and one for sending messages between that other chat process, but this would increase complexity and this is just meant to be a simple implementation.
Related
This is bugging me for days.
The problem is my not so good understanding of pointers and addresses in c so i hope someone will be able to help me out.
I need to pass some strings as input parameters and create as much producer processes + one consumer process.
Producers should take the string apart and send each letter as message to queue. At the end it should send NULL("").
The consumer should wait for messages and print them out.
The whole code and output is below. By looking at the output i'd say that the problem is somewhere in the producer. To be more precise it is in the first line of te for loop but i can not get it right.
manager.c - This is the main program that operates processes
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
int main( int argc, char *argv[], char *envp[] ) {
printf("Starting %d processes \n", argc);
putenv("MSG_KEY=12345");
for (int i = 1; i < argc; i++) {
printf("argv[%d] = %s \n", i, argv[i]);
pid_t producer = fork();
if (producer == 0) {
printf("producer pid - %d\n", getpid());
execl("./producer", "producer", argv[i], NULL);
}
}
pid_t consumer = fork();
if (consumer == 0) {
printf("consumer pid - %d\n", getpid());
execl("./consumer", "consumer", NULL);
exit(0);
} else {
printf("manager pid - %d\n", getpid());
wait(NULL);
}
int status;
while(waitpid(consumer, &status, 0) == -1);
printf("DONE consumer\n");
printf("DONE manager\n");
return 0;
}
producer.c
/*
** writes to message queue
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[1];
};
int main( int argc, char *argv[], char *envp[] ) {
struct my_msgbuf buf;
int msqid;
key_t key = atoi(getenv("MSG_KEY"));
if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
buf.mtype = getpid();
// I believe the error is in this for loop or to be more precise in the first line of the for loop.
// takes the first argument and sends characters in separate messages
for (int i = 0; i < strlen(argv[1]); ++i) {
char c = argv[1][i];
strcpy(buf.mtext, &c);
printf ("Sending -%s-\n", buf.mtext);
if (msgsnd(msqid, (struct msgbuf *)&buf, strlen(buf.mtext)+1, 0) == -1)
perror("msgsnd");
}
// send NULL at the end
memcpy(buf.mtext, "", strlen("")+1);
if (msgsnd(msqid, (struct msgbuf *)&buf, strlen("")+1, 0) == -1)
perror("msgsnd");
return 0;
}
consumer.c
/*
** reads from message queue
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[1];
};
int main( int argc, char *argv[], char *envp[] ) {
struct my_msgbuf buf;
int msqid;
key_t key = atoi(getenv("MSG_KEY"));
if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
int flag = 0;
int wait_counter = 0;
while (wait_counter < 10) {
msgrcv(msqid, (struct msgbuf *)&buf, sizeof(buf)-sizeof(long), 0, flag);
if (errno == ENOMSG){
wait_counter++;
printf ("Sleaping for one second...zzzZZZzzz...%d\n", wait_counter);
usleep(1000 * 1000);
} else {
printf("Received:\n\ttype: -%ld- \n\tchar: -%s- \n", buf.mtype, buf.mtext);
int compare = strcmp(buf.mtext, "");
if(compare == 0){
printf("NULL received\n");
flag = IPC_NOWAIT;
} else {
flag = 0;
}
wait_counter = 0;
}
errno = 0;
}
if (msgctl(msqid, IPC_RMID, NULL) == -1) {
perror("msgctl");
exit(1);
} else {
printf("Message queue removed\n");
}
return 0;
}
Output - i have to give you the screenshot here because c/p deletes the problem and everything looks ok
Any help will be much appreciated! Thank you!
Error when used as suggested in the #sergeya answer below
*buf.mtext = c;
Your problem (one of them, at least) is here:
char c = argv[1][i];
strcpy(buf.mtext, &c);
strcpy() will try to copy as many characters as there are until nul-terminator '\0' is encountered, starting from c. You need to copy one character exactly, so you just need
*buf.mtext = c;
As i said, the problem was in the producer inside the for loop. I will put the change here. Hope it helps anyone with the similar problem.
#SergeyA gave me excellent clue where the problem is so i switched from "strcpy" to "memcpy" and i have copied just the first character and not the nul-terminator.
Also i have changed the "strlen" to "sizeof" and removed the +1.
Producer.c
...
for (int i = 0; i < strlen(argv[1]); ++i) {
char c = argv[1][i];
memcpy(buf.mtext, &c, sizeof(&c)+1);
printf ("Sending -%c-\n", buf.mtext);
if (msgsnd(msqid, (struct msgbuf *)&buf, sizeof(buf.mtext), 0) == -1)
perror("msgsnd");
}
...
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);
}
}
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);
}
}
I am trying to implement threading, a binary semaphore, and message queues in a client and server program. Everything works, except for the reply in my server to send a response back to the client. When I uncomment the reply, the server loops infinitely after receiving a message.
They both use a message.h header file that is a struct containing:
contents (character), id(int), and mtype(int).
// server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "message.h"
int sqid, cqid, pid;
msg m, n;
sem_t sem_var;
key_t key;
void requestSem();
void setSem();
void unlockSem();
void reply();
void readQueue();
void listener(void *ptr);
int main() {
key = ftok(".", 'z');
sqid = msgget(key, IPC_CREAT | 0600);
if(sqid < 0) {
perror("Error creating the message queue.\n");
}
pthread_t thread1;
pthread_t thread2;
pthread_t thread3;
char *msg1 = "Thread 1";
char *msg2 = "Thread 2";
char *msg3 = "Thread 3";
pthread_create(&thread1, NULL, (void *) &listener, (void *) msg1);
pthread_create(&thread2, NULL, (void *) &listener, (void *) msg2);
pthread_create(&thread3, NULL, (void *) &listener, (void *) msg3);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
}
// always listen for messages
void listener(void *ptr) {
while (1) {
requestSem();
setSem();
readQueue();
unlockSem();
//reply();
}
}
void readQueue()
{
// print the proccess ID and thread ID
printf("Process ID: %d, Thread ID: %d\n", getpid(), pthread_self());
// receive message
if(msgrcv(sqid,&m,sizeof(struct msg),0,0) < 0) {
perror("Error receiving a message.\n");
}
printf("Message was received...\n");
fprintf(stderr, "The contents are: %s\n", &m.contents);
fprintf(stderr, "The client's ID is: %d\n", (&m)->id);
fprintf(stderr, "The thread's ID is: %d\n", pthread_self());
}
void requestSem()
{
// request semaphore (lock)
sem_init(&sem_var, 1, 1);
printf("Semaphore requested.\n");
}
void setSem()
{
// lock semaphore
sem_wait(&sem_var);
printf("Semaphore set.\n");
}
void unlockSem()
{
// unlock semaphore
sem_post(&sem_var);
printf("Semaphore unlocked.\n");
}
void reply()
{
// send reply
printf("got here\n");
pid = (&m)->id;
cqid = msgget(pid, 0600);
n.contents = (&m)->contents;
n.mtype = 0;
n.id = getpid();
if(msgsnd(cqid, &n,sizeof(struct msg),0) < 0) {
perror("Msg send error");
}
msgctl(sqid,IPC_RMID,NULL);
}
// client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include "message.h"
int main() {
// initialize variables
int mqid, rqid;
msg m;
key_t key;
// initialize message
int pid;
pid = getpid();
m.id = pid;
m.mtype = 1;
// create message queue and response queue
key = ftok(".", 'z');
mqid = msgget(key, 0600);
rqid = msgget(pid, IPC_CREAT | 0600);
if(mqid < 0) {
perror("Error creating the message queue.\n");
}
if (rqid < 0)
{
perror("Error creating the message queue.\n");
}
// loop forever, can send as many messages as you want
while(1) {
fprintf(stderr, "The ID of the client is: %d\n", pid);
// prompt for user input
printf("Enter one character to send: \n");
scanf("%s", &m.contents);
// send message
if(msgsnd(mqid, &m,sizeof(struct msg), 1) < 0) {
perror("Error sending the message.");
}
//msgctl(mqid,IPC_RMID,NULL);
printf("Message was sent successfully!\n");
// receive response
printf("Waiting for a reply...\n");
if(msgrcv(rqid,&m,sizeof(msg), 0, 0) < 0)
{
perror("Error receiving a message.\n");
}
printf("Message was received.\n");
fprintf(stderr, "The contents are: %s\n", &m.contents);
}
}
Thank you in advance for any help. Everything functions as it's supposed to when reply is commented out within listener in the server. Uncommenting it creates an infinite loop.
the reason the server never exits is because each thread has a
while(1)
loop and no way to exit that loop
what I want is this:
1 main process that create 4 children process where:
-> The main process receive messages from the children through the queue and print the message recieved.
-> The children send messages (a string with priority+message) through the queue and finish.
All in a while (1), so, when you CTRL+C, the children finish first (the signal is in the children code) and then, the parent finish.
For the moment, I am having problem with mq_send() and mq_recieve().
Well, this is my code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <mqueue.h>
void sigint_handler()
{
/*do something*/
printf("killing process %d\n",getpid());
exit(0);
}
int main ()
{
mqd_t mqd;
struct mq_attr atributos;
// atributos.mq_maxmsg = 10;
//
// atributos.mq_msgsize = 50;
printf ("This is the parent. PID=%d\n",getpid ());
int num_children = 4;
int i;
int pid;
int status;
char buffer [50];
while (1){
for (i=0; i<num_children ;i++){
if ((pid=fork()==0)){
signal(SIGINT, sigint_handler);
int prio = rand () % 3;
printf ("%d\n",prio);
char * msg= "Hi dude";
char * priority=NULL;
if (prio == 0){
priority = "NORMAL";
}
else {
priority = "URGENT";
}
char* toSend=NULL;
toSend = malloc(strlen(msg)+1+strlen(priority));
strcpy (toSend,priority);
strcat (toSend,msg);
printf ("%s\n",toSend);
if ((mqd=mq_open("/queue.txt", O_CREAT|O_WRONLY, 0777, &atributos))==-1){
printf ("Error mq_open\n");
exit(-1);
}
if (mq_send(mqd, msg , strlen(toSend), prio) == -1) {
printf ("Error mq_send\n");
exit (-1);
}
mq_close(mqd);
printf ("This is children %d\n",getpid());
sleep(1);
exit(0);
}
}
if ((mqd=mq_open("/queue.txt", O_CREAT|O_WRONLY, 0777, &atributos))==-1){
printf ("Error mq_open\n");
exit(-1);
}
//Rest Parent code
if (mq_receive(mqd, buffer, strlen(buffer),0)==-1){
printf ("Error mq_recieve\n");
exit(-1);
}
printf("Received: %s\n",buffer);
sleep (1);
waitpid(pid,&status,0);
printf ("This is the parent again %d, children should have finished\n",getpid());
mq_close(mqd);
}
}
I don't know why both mq_send() and mq_receive() returns -1, what am I doing wrong¿?
And you you see something wrong in my code in order to do what I intend apart from the error I am talking about, let me know.
Thank you in advance, I appreciate any help.
user58697 touched upon the biggest problems.
(1) Your queue opens were failing with EINVAL because you wee passing uninitialized attributes because you commented out assignments.
(2) You were opening both queues for write-only. The parent queue needed to be opened in read mode.
(3) Execute permissions don't mean anything to a queue so 777 permissions while not invalid are unnecessary.
(4) Your sends/receives were failing because of invalid lengths. In many if not most cases it is just easier and safer to allocate your buffers to the length attribute of the queue. In this case you know the length before hand but in programs that don't you can get the value via mq_getattr.
(5) You weren't calling srand to seed the RNG before calling rand.
(6) You had a memory leak where you allocate space (unnecessarily) for the message but never freed it.
(7) What you were trying to do with passing priorities is redundant. POSIX MQs have priorities already built in. You can just use those.
I took out some of the fluff (mainly the loops & signals) to concentrate more on the queue aspects of your program.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <mqueue.h>
int main()
{
srand(time(NULL));
mqd_t mqd;
struct mq_attr atributos = {.mq_maxmsg = 10, .mq_msgsize = 50};
int i;
int pid;
int status;
int num_children = 4;
char buffer[atributos.mq_msgsize];
for (i = 0; i < num_children; i++)
{
if ((pid = fork() == 0))
{
int prio = rand () % 3;
char* msg = "Hi dude";
strncpy (buffer, msg, sizeof(buffer));
if ((mqd = mq_open("/queue.txt", O_CREAT | O_WRONLY, 0666, &atributos)) == -1)
{
perror("child mq_open");
exit(1);
}
if (mq_send(mqd, buffer, sizeof(buffer), prio) == -1)
{
perror("mq_send");
exit(1);
}
mq_close(mqd);
exit(0);
}
}
// parent
if ((mqd = mq_open("/queue.txt", O_CREAT | O_RDONLY, 0666, &atributos)) == -1)
{
perror("parent mq_open");
exit(1);
}
int priority;
for (int i = 0; i < num_children; ++i)
{
if (mq_receive(mqd, buffer, sizeof(buffer), &priority) == -1)
{
perror("mq_recieve");
exit(1);
}
printf("Received (%s): %s\n", (priority == 0) ? "NORMAL" : "URGENT", buffer);
pid_t childpid;
if ((childpid = waitpid(-1, &status, 0)) > 0)
{
if (WIFEXITED(status))
printf("PID %d exited normally. Exit status: %d\n",
childpid, WEXITSTATUS(status));
else
if (WIFSTOPPED(status))
printf("PID %d was stopped by %d\n",
childpid, WSTOPSIG(status));
else
if (WIFSIGNALED(status))
printf("PID %d exited due to signal %d\n.",
childpid,
WTERMSIG(status));
}
}
mq_close(mqd);
}
First and foremost, when a system call fails, print errno (and strerror(errno)).
Now, obvious mistakes:
as was mentioned, you need a read access to be able to mq_receive()
what is strlen(buffer)?
you are passing attributes without initializing them.
To summarize, print errno and see what is wrong.
I am trying to implement a IPC mechanism for telephone conversation using message queues in C. I have created two .c files, one for caller and one for receiver. In each .c file i have created two threads , one for sending messages and another for receiving messages. Each thread creates its message queue. The send message thread from caller and the receive message thread from receiver share the same queue and same for the other.
The message queues are being created but whenever i enter some message to be sent , it fails. The msgsnd(-,-,-,-) always returns -1.
The caller.c file is as follows :
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
struct msgbuf
{
long mtype;
char mtext[50];
}SEND_BUFFER,RECEIVE_BUFFER;
int send_msgQ_id, receive_msgQ_id;
key_t send_key,receive_key;
void * send_message(void * a)
{
send_key = ftok("Caller.c", 'B');
if(send_key==-1)
{
printf("\n caller send key error");
exit(1);
}
send_msgQ_id = msgget(send_key, 0666 | IPC_CREAT);
if(send_msgQ_id==-1)
{
printf("\n caller send msgget error");
exit(1);
}
printf("\n Enter lines of text, ^D to quit:\n");
while(fgets(SEND_BUFFER.mtext, sizeof(SEND_BUFFER.mtext), stdin) != NULL)
{
SEND_BUFFER.mtype = 0;
int len = strlen(SEND_BUFFER.mtext);
if (SEND_BUFFER.mtext[len-1] == '\n')
SEND_BUFFER.mtext[len-1] = '\0';
printf("\n Attemping to send %s\n", SEND_BUFFER.mtext);
if(msgsnd(send_msgQ_id, &SEND_BUFFER, len+1, 0)==-1)
printf("\n msg sendign error\n");
}
int i =0;
while(i<9999)
i++;
msgctl(send_msgQ_id, IPC_RMID, NULL);
return;
}
void * receive_message(void * a)
{
receive_key = ftok("Receiver.c", 'B');
if(receive_key==-1)
{
printf("\n caller receive key error");
exit(1);
}
receive_msgQ_id = msgget(receive_key, 0777 | IPC_CREAT);
if(receive_msgQ_id==-1)
{
printf("\n caller receive msgget error");
exit(1);
}
printf("\n Ready to receive ");
while(1)
{
if( msgrcv(receive_msgQ_id, &RECEIVE_BUFFER, sizeof(RECEIVE_BUFFER.mtext), 0, 0)!=-1)
printf("Received : %s\n", RECEIVE_BUFFER.mtext);
}
return;
}
void initialize()
{
pthread_t send_thread,receive_thread;
pthread_create(&send_thread,NULL,send_message,NULL);
pthread_create(&receive_thread,NULL,receive_message,NULL);
pthread_join(send_thread,NULL);
pthread_join(receive_thread,NULL);
return;
}
int main()
{
printf("\n\n *** Caller Program ***\n");
initialize();
return 0;
}
The receiver.c file is as follows (it is similar to the caller.c file) :
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
struct msgbuf
{
long mtype;
char mtext[50];
}SEND_BUFFER,RECEIVE_BUFFER;
int send_msgQ_id, receive_msgQ_id;
key_t send_key,receive_key;
void * send_message(void * a)
{
send_key = ftok("Receiver.c", 'B');
if(send_key==-1)
{
printf("\n receiver send key error");
exit(1);
}
send_msgQ_id = msgget(send_key, 0777);
if(send_msgQ_id==-1)
{
printf("\n receiver msgget error ");
exit(1);
}
printf("\n Enter lines of text, ^D to quit:\n");
SEND_BUFFER.mtype = 0;
while(fgets(SEND_BUFFER.mtext, sizeof(SEND_BUFFER.mtext), stdin) != NULL)
{
int len = strlen(SEND_BUFFER.mtext);
if (SEND_BUFFER.mtext[len-1] == '\n')
SEND_BUFFER.mtext[len-1] = '\0';
msgsnd(send_msgQ_id, &SEND_BUFFER, len+1, 0);
}
int i =0;
while(i<9999)
i++;
msgctl(send_msgQ_id, IPC_RMID, NULL);
return;
}
void * receive_message(void * a)
{
receive_key = ftok("Caller.c", 'B');
if(receive_key==-1)
{
printf("\n receiver receiver key error");
exit(1);
}
receive_msgQ_id = msgget(receive_key, 0666);
if(receive_msgQ_id==-1)
{
printf("\n msgget error");
exit(1);
}
while(1)
{
if(msgrcv(receive_msgQ_id, &RECEIVE_BUFFER, sizeof(RECEIVE_BUFFER.mtext), 0, 0)==-1)
printf("\n msg receiving error");
else
printf("Received : %s\n", RECEIVE_BUFFER.mtext);
}
return;
}
void initialize()
{
pthread_t send_thread,receive_thread;
pthread_create(&receive_thread,NULL,receive_message,NULL);
pthread_create(&send_thread,NULL,send_message,NULL);
pthread_join(send_thread,NULL);
pthread_join(receive_thread,NULL);
return;
}
int main()
{
printf("\n\n *** Receiver Program ***\n");
initialize();
return 0;
}
I need that both the caller and sender can receive and send messages at their free will.
The errno you're getting indicates you're passing an invalid argument to msgsnd. According to the man page for msgsnd:
[EINVAL]
The value of msqid is not a valid message queue identifier, or the value of mtype is less than 1; or the value of msgsz is less than 0 or greater than the system-imposed limit.
Blockquote
My guess would be that msqid is the offending parameter. Either check the value in a debugger or print it out.
EDIT: Mike Wilkins spotted it. His comment:
mtype is likely the issue (not msqid). mtype needs to be > 0. The code
in the OP specifically sets it to 0