Ipc using mesage queues gets caller key error - c

I tried to run the message queue program of a telephonic conversation between a caller and a receiver given here with the correction stated. I keep getting the following result:
./caller
Caller Program
Caller send key error
Caller send key error
Receiver send key error
while running the caller executable.
The caller.c is:
#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[140];
}msg_buf;
int send_msg_id,receive_msg_id;
key_t send_key,receive_key;
void *send_message(void *a)
{
send_key=ftok("Caller1.c",'A');
if (send_key==-1)
{
printf("\nCaller send key error");
exit(1);
}
send_msg_id=msgget(send_key,0666 | IPC_CREAT);
if (send_msg_id==-1)
{
printf("\nCaller send msgget error");
exit(1);
}
printf("\nCALLER:");
while (fgets(msg_buf.mtext,sizeof(msg_buf.mtext),stdin)!=NULL)
{
msg_buf.mtype=1;
int len=strlen(msg_buf.mtext);
if (msg_buf.mtext[len-1]=='\n');
msg_buf.mtext[len-1]='\0';
if (msgsnd(send_msg_id,&msg_buf,len+1,0)==-1)
printf("\nMsg sending error\n");
}
int i=0;
while(i<9999)
i++;
msgctl(send_msg_id,IPC_RMID,NULL);
return;
}
void *receive_message(void *a)
{
receive_key=ftok("Receiver1.c",'B');
if (receive_key==-1)
{
printf("\nReceiver send key error");
exit(1);
}
send_msg_id=msgget(receive_key,0777|IPC_CREAT);
if (receive_msg_id==-1)
{
printf("\nCaller msgrcv error");
exit(1);
}
printf("\n<<<");
while(1)
{
if(msgrcv(receive_msg_id,&msg_buf,sizeof(msg_buf.mtext),1,0)!=-1)
printf("<<<%s\n",msg_buf.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("\nCaller Program\n");
initialize();
return 0;
}
The receiver program is the same error. The reciever.c is almost the same as the the caller.c:
#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[140];
}msg_buf;
int send_msg_id,receive_msg_id;
key_t send_key,receive_key;
void *send_message(void *a)
{
send_key=ftok("Receiver1.c",'A');
if (send_key==-1)
{
printf("\nReceiver send key error");
exit(1);
}
send_msg_id=msgget(send_key,0777 | IPC_CREAT);
if (send_msg_id==-1)
{
printf("\nReceiver send msgget error");
exit(1);
}
printf("\nRECEIVER:");
while (fgets(msg_buf.mtext,sizeof(msg_buf.mtext),stdin)!=NULL)
{
msg_buf.mtype=1;
int len=strlen(msg_buf.mtext);
if (msg_buf.mtext[len-1]=='\n')
msg_buf.mtext[len-1]='\0';
if (msgsnd(send_msg_id,&msg_buf,len+1,0)==-1)
printf("\nMessage sending error");
}
int i=0;
while(i<9999)
i++;
msgctl(send_msg_id,IPC_RMID,NULL);
return;
}
void *receive_message(void *a)
{
receive_key=ftok("Caller1.c",'B');
if (receive_key==-1)
{
printf("\nReceiver send key error");
exit(1);
}
send_msg_id=msgget(receive_key,0666|IPC_CREAT);
if (receive_msg_id==-1)
{
printf("\nCaller msgrcv error");
exit(1);
}
printf("\n<<<");
while(1)
{
if(msgrcv(receive_msg_id,&msg_buf,sizeof(msg_buf.mtext),1,0)!=-1)
printf("<<<%s\n",msg_buf.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("\nReceiver Program\n");
initialize();
return 0;
}
The receiver gives the same error as the caller:
Receiver Program
Receiver send key error
Receiver send key error

Related

IPC Message queue not works with forked process

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);
}
}

Blank msgrcv buffer

I tried to run the message queue program of a telephonic conversation between a caller and a receiver given here with the correction stated.I keep getting the following result:
./caller
Caller Program
<<<
CALLER:Hello!!
while running the caller executable.The message buffer while receiving is empty.I don't know why.Please help!!
The caller.c is:
#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[140];
}msg_buf;
int send_msg_id,receive_msg_id;
key_t send_key,receive_key;
void *send_message(void *a)
{
send_key=ftok("Caller1.c",'A');
if (send_key==-1)
{
printf("\nCaller send key error");
exit(1);
}
send_msg_id=msgget(send_key,0666 | IPC_CREAT);
if (send_msg_id==-1)
{
printf("\nCaller send msgget error");
exit(1);
}
printf("\nCALLER:");
while (fgets(msg_buf.mtext,sizeof(msg_buf.mtext),stdin)!=NULL)
{
msg_buf.mtype=1;
int len=strlen(msg_buf.mtext);
if (msg_buf.mtext[len-1]=='\n');
msg_buf.mtext[len-1]='\0';
if (msgsnd(send_msg_id,&msg_buf,len+1,0)==-1)
printf("\nMsg sending error\n");
}
int i=0;
while(i<9999)
i++;
msgctl(send_msg_id,IPC_RMID,NULL);
return;
}
void *receive_message(void *a)
{
receive_key=ftok("Receiver1.c",'B');
if (receive_key==-1)
{
printf("\nReceiver send key error");
exit(1);
}
send_msg_id=msgget(receive_key,0777|IPC_CREAT);
if (receive_msg_id==-1)
{
printf("\nCaller msgrcv error");
exit(1);
}
printf("\n<<<");
while(1)
{
if(msgrcv(receive_msg_id,&msg_buf,sizeof(msg_buf.mtext),1,0)!=-1)
printf("<<<%s\n",msg_buf.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("\nCaller Program\n");
initialize();
return 0;
}

IPC mechanism using message queues in C

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

UNIX message queue msgrcv failed to receive message

Dear Friends,
Any idea why the msgrcv is receiving a blank buffer?
Here is the code:
enter code here
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
typedef struct mymsg {
long mtype;
char mtext[24];
}mymsg;
int main()
{
int msqid;
mymsg msg,buff;
msqid=msgget(IPC_PRIVATE,IPC_CREAT|IPC_EXCL);
if(msqid==-1){
perror("FAiled to create message queue\n");
}
else{
printf("Message queue id:%u\n",msqid);
}
msg.mtype=1;
strcpy(msg.mtext,"This is a message");
if(msgsnd(msqid,&msg,sizeof(msg.mtext),0)==-1){
perror("msgsnd failed:");
}
else{
printf("Message sent successfully\n");
}
//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
// msgrcv(msqid,buff.mtext,sizeof(msg.mtext),1,0); This was error
msgrcv(msqid,&buff,sizeof(msg.mtext),1,0); // This is correct (Thanks to Erik)
printf("The message received is: %s\n",buff.mtext);
}
Output:
[root#dhcppc0 message_queue]# ./a.out
Message queue id:294919
Message sent successfully
The message received is:
1,1 Top
msgbuf.mtype must be set to 1 - since you're telling msgrcv that you want messages of type 1.
Alternatively, you could set msgbuf.mtype to any positive value, and then tell msgrcv that you want any message type by passing 0 as the msgtyp argument.
Also, msgrcv expects a pointer to a msgbuf:
msgrcv(msqid,&buff,sizeof(msg.mtext),1,0);
EDIT: Tested working source:
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
typedef struct mymsg {
long mtype;
char mtext[24];
}mymsg;
int main()
{
int msqid;
mymsg msg,buff;
msqid=msgget(IPC_PRIVATE,IPC_CREAT|IPC_EXCL);
if(msqid==-1){
perror("FAiled to create message queue\n");
}
else{
printf("Message queue id:%u\n",msqid);
}
msg.mtype=1; // was there failed to copy
strcpy(msg.mtext,"This is a message");
if(msgsnd(msqid,&msg,sizeof(msg.mtext),0)==-1){
perror("msgsnd failed:");
}
else{
printf("Message sent successfully\n");
}
//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgrcv(msqid,&buff,sizeof(msg.mtext),1,0);
printf("The message received is: %s\n",buff.mtext);
}

Why do I get compiler error: ‘SIGSUR1’ was not declared in this scope?

I want to use the SIGNAL SIGSUR1 to communicate between two processes, but I get the compiler error:
error: ‘SIGSUR1’ was not declared in this scope .
What's the fix?
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
void cursor(int y)
{
int i;
printf("%c[%d;%df",0x1B,y,0);
}
void handle(int fd,int turtle_current_pos){
fcntl(fd,F_SETFL,O_NONBLOCK);
write(fd,&turtle_current_pos,sizeof(int));
}
int getdist(int fd,int hare_pos,int max_dist)
{
int r,n;
raise(0,SIGSUR1);
fcntl(fd,F_SETFL,O_NONBLOCK);
if((n=read(fd,&r,sizeof(int)))){
if((hare_pos-r-max_dist)>0)
return 0;
else
return 1;
}
}
void print(char b,int a){
fflush(stdout);
if(b=='T') cursor(10);
else cursor(15);
for(int i=0;i<a;i++) printf(" ");
printf("%c\n",b);
}
void turtle(int fd,int sec1,int turtle_speed){
signal(SIGSUR1,handle);
struct timeval b;
int flag=1,turtle_current_pos,turtle_previous_pos=0,sec2;
turtle_current_pos=0;
while(turtle_current_pos<100){
sleep(2);
gettimeofday(&b,NULL);
sec2=b.tv_sec;
//printf("%d\n",sec2);
turtle_current_pos=(sec2-sec1)*turtle_speed;
fflush(stdout);
if((turtle_current_pos-turtle_previous_pos)>=1){
turtle_previous_pos=turtle_current_pos;
print('T',turtle_previous_pos);
}
}
}
int main(){
system("clear");
pid_t pid,God_pid,hare_pid,Report_pid;
int max_dist=10,sleep_time=1,pipe1[2],speed_hare=5,speed_turtle=1;
pipe(pipe1);
pid=fork();
if(pid!=0){
int hare_current_pos=0,hare_previous_pos=0,sec1,sec2;
struct timeval n;
gettimeofday(&n,NULL);
sec1=n.tv_sec;
sec2=sec1;
close(pipe1[1]);
while(hare_current_pos<100){
sleep(1);
if(getdist(pipe1[0],hare_current_pos,max_dist)==0){
sleep(sleep_time);
gettimeofday(&n,NULL);
sec1=n.tv_sec;
sec2=sec1;
fflush(stdout);
}
else{
gettimeofday(&n,NULL);
sec2=n.tv_sec;
gettimeofday(&n,NULL);
hare_current_pos+=speed_hare*(sec2-sec1);
//printf("\n%d",hare_current_pos);
fflush(stdout);
if(hare_current_pos-hare_previous_pos){
print('H',hare_current_pos);
hare_previous_pos=hare_current_pos;
}
}
}
}
else{
close(pipe1[0]);
struct timeval b;
gettimeofday(&b,NULL);
fflush(stdout);
turtle(pipe1[1],b.tv_sec,speed_turtle);
}
}
Try SIGUSR1 instead.

Resources