Message queue is giving me an invalid argument - c

I'm having some trouble with my code. It should create a message queue and send a message, than wait some time for another program to receive that message and answer. The problem is, when I run it, I get an invalid argument both on the msgsnd and on the msgrcv.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/msg.h>
typedef struct my_msg{
long type;
char text[100];
char sqdr;
}message;
static void score(int messagge_id, char* A_B){
message send;
send.type=1;
strcpy(send.text, "Try to score");
send.sqdr = *A_B;
if((msgsnd(messagge_id, &send, sizeof(send), 0))<0)perror("Error msgsnd\n");
sleep(3);
if((msgrcv(messagge_id, &send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n");
int test=atoi(send.text);
printf("%d\n", test);
}
int main(){
int caso, key;
char team= 'A';
key=1234;
int msg_id=msgget(key, S_IRUSR|S_IWUSR);
printf("Try function score\n");
score(msg_id, &team);
printf("After score\n");
return 0;
}

You need to ensure that the message queue is created. You either use the key IPC_PRIVATE or you add IPC_CREAT to the flags. You also need to try to read the message correctly. You sent a 'type 1' message and attempted to read a 'type 4' message, so the read hangs.
This code also removes the message queue. That's not critical if it is a private queue (such queues are deleted when the program terminates), but it is important for queues using IPC_CREAT and a user-defined key. (I also changed the message text so that atoi() returned something more interesting — and convincing — than zero. The code also uses separate send and receive buffers so that we know the code is not cheating and reusing data already in the buffer.)
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <fcntl.h>
typedef struct my_msg
{
long type;
char text[100];
char sqdr;
} message;
static void score(int messagge_id)
{
message send;
message recv;
send.type = 1;
strcpy(send.text, "47 tries to score");
send.sqdr = 'A';
if ((msgsnd(messagge_id, &send, sizeof(send), 0)) < 0)
perror("Error msgsnd");
printf("Dozing...\n");
sleep(3);
printf("Unslumbering...\n");
if ((msgrcv(messagge_id, &recv, sizeof(recv), -4, 0)) == -1)
perror("Error msgrcv");
int test = atoi(recv.text);
printf("%d\n", test);
}
int main(void)
{
int key = 1234;
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
// int key = IPC_PRIVATE;
// int flags = S_IRUSR|S_IWUSR;
int msg_id = msgget(key, flags);
if (msg_id < 0)
perror("Error msgget");
else
{
printf("Try function score\n");
score(msg_id);
printf("After score\n");
if (msgctl(msg_id, IPC_RMID, 0) < 0)
perror("Error msgctl");
}
return 0;
}
Sample output:
Try function score
Dozing...
Unslumbering...
47
After score
There's a 3 second pause between 'Dozing' and 'Unslumbering', of course.

use like this:-
if((msgsnd(messagge_id, (void *)&send, sizeof(send), 0))<0)perror("Error msgsnd\n");
if((msgrcv(messagge_id, (void *)&send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n");

Related

stack smashing when receiving a single message through message queues

I have the following sender:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>
typedef struct message {
long int mtype;
int mtext[200];
} message;
int main(int argc, char *argv[]) {
// msg queue
int msgid;
message msg;
key_t key;
// create msg queue key
if ((key = ftok("master.c", 'b')) == -1) {
perror("ftok");
}
// create msg queue
if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
perror("msgget");
}
msg.mtype=10;
msg.mtext[0] = 1;
if ((msgsnd(msgid, &msg, sizeof(message), 0)) == -1) {
perror("msgsnd");
}
sleep(5);
// TODO: uncomment section
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl");
}
return 0;
}
And receiver:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>
typedef struct message {
long int mtype;
int mtext[200];
} message;
int main(int argc, char *argv[]) {
// msg queue
message msg;
int msgid;
key_t key;
// create msg queue key
if ((key = ftok("master.c", 'b')) == -1) {
perror("ftok");
}
// create msg queue
if ((msgid = msgget(key, 0666)) == -1) {
perror("msgget");
}
if ((msgrcv(msgid, &msg, sizeof(message), 10, 0)) == -1) {
perror("msgrcv");
}
printf("%d\n", msg.mtext[0]);
return 0;
}
The problem is that when I run both of them, I am getting
*** stack smashing detected ***: terminated
Aborted (core dumped)
The above phrase is shown after the whole code has executed as intended but still, it means that something is not right. If, though, I place msgrcv in an infinite loop, everything runs as intended and no warning is raised. Since I am both writing and reading the same size of data, where could the error come from?
According to the documentation, the msgsz argument to msgrcv should indicate the size (in bytes) of the .mtext member of the message structure, rather than the size of the entire structure.
That structure will typically be 4 or 8 bytes (depending on how long int is defined) larger than the available buffer, so you are likely writing beyond the available/assigned memory – causing undefined behaviour.
One possible effect of that UB is corruption of the stack allocated for the main function; if that function never returns (as when you add the infinite loop), that stack corruption may not manifest itself.

Message queue error: No message of desired type

I am trying to understand how message queues work. I created this little program where the child process sends a message to the parent process. Most of the times, it works, but sometimes I would recieve the error: Error parent: No message of desired type. I tried also to wait for the child process to finish, but I would still get the error.
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
struct msg{
long mtype;
char text[100];
};
int key = ftok(".", 10);
int qid = msgget(key, 0666|IPC_CREAT);
int pid = fork();
if(pid == 0){
struct msg send;
send.mtype = 1;
strcpy(send.text, "hello");
if(msgsnd(qid, (void*)&send, strlen(send.text), IPC_NOWAIT)<0){
printf("Error child: ");
}
}
else{
struct msg recieve;
if(msgrcv(qid, (void*)&recieve, 100, 1, IPC_NOWAIT)<0){
perror("Error parent: ");
};
printf("%s\n", recieve.text);
}
return 0;
}
Thanks.
http://pubs.opengroup.org/onlinepubs/7908799/xsh/msgrcv.html
The argument msgflg specifies the action to be taken if a message of the desired type is not on the queue. These are as follows:
If (msgflg & IPC_NOWAIT) is non-zero, the calling thread will return immediately with a return value of -1 and errno set to [ENOMSG]
...
You're specifying IPC_NOWAIT which means you're not giving the child process enough time to produce any message. If you drop that from the parameter msgflg, i.e.
if(msgrcv(qid, (void*)&recieve, 100, 1, 0) < 0)
The parent process will block until something is available in the queue.

individual char extraction in c while using messages and msgsnd

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

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

Basic unix server-client IPC(msg queue) issue

I'm working on a problem wich implies a basic running server client(done one before). the problem is that I run server than I run client. My msg Que is created i nboth client takes my char as input sends it, i get the confirmation print but my server msgrcv isn't responding.
s.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include "struc.h"
int main(){
int qt;
struct msg m;
qt = msgget(1271,IPC_CREAT|IPC_EXCL|0600);
if(qt < 0){ perror("Error MSGGET()\n");}
printf("msg queue created!\n");
if(msgrcv(qt,&m,sizeof(struct msg),0,0)<0){
perror("Msg recive error");
}
printf("msg recived!\n");
msgctl(qt,IPC_RMID,NULL);
return 0;
}
c.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include "struc.h"
int main(){
int qt;
struct msg m;
qt = msgget(1271,0);
if(qt < 0){ perror("~~~ Error MSGGET()\n");}
printf("msg created!\n");
printf("Enter one char: !\n");
scanf("%c",&m.c);
msgsnd(qt, &m,sizeof(struct msg),0);
printf("msg sent!\n");
return 0;
}
struc.h
struct msg{
long mtype;
// matrix M;
char c;
};
(By creating the 3 files you cna test it yourself. Any idea is welcome maybe i missed something)
You should do this to verify that sending doesn't fail.
if(msgsnd(qt, &m,sizeof(struct msg),0)) < 0) {
perror("Msg send error");
}
You should also heed the docs for msgsnd:
The msgp argument is a pointer to caller-defined structure of the
following general form:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
That is, you have to set the mtype in the message you send to be > 0. Currently it is uninitialized, so you should do:
m.mtype = 1;
if(msgsnd(qt, &m,sizeof(struct msg),0)) < 0) {
perror("Msg send error");
}

Resources