Reputation: 1307
I'm doing my first practice with message queues. I want mq_receive to block so I do not have O_NOBLOCK turned on.
The mq_receive method is returning, and perror() is printing "message too long". This is before I've even sent the message.
The ATM sends the messages:
void* run_ATM(void* arg) {
int status;
char accountNumber[15];
cout << "ATM is running" << endl;
cout << "Please input an account number > ";
cin >> accountNumber;
status = mq_send(PIN_MSG, accountNumber, sizeof(accountNumber), 1);
}
The database receives them
void* run_DB(void* arg){
cout << "Database server running" << endl;
int status;
char received_acct_number[30];
while(1){
status = mq_receive(PIN_MSG, received_acct_number, 100, NULL);
if (status < 0){
perror("error ");
} else {
cout << "received account number\t" << received_acct_number << endl;
}
}
}
This is just preliminary code - so it will eventually do more. I just wanted to get a basic working example.
EDIT: other code required to get this to run:
#define PIN_MSG_NAME "/pin_msg"
#define DB_MSG_NAME "/db_msg"
#define MESSAGE_QUEUE_SIZE 15
pthread_t ATM;
pthread_t DB_server;
pthread_t DB_editor;
void* run_ATM(void* arg);
void* run_DB(void* arg);
static struct mq_attr mq_attribute;
static mqd_t PIN_MSG, DB_MSG;
int main(int argc, char const *argv[])
{
pthread_attr_t attr;
mq_attribute.mq_maxmsg = 10; //mazimum of 10 messages in the queue at the same time
mq_attribute.mq_msgsize = MESSAGE_QUEUE_SIZE;
PIN_MSG = mq_open(PIN_MSG_NAME, O_CREAT | O_RDWR, 0666, &mq_attribute);
DB_MSG = mq_open(DB_MSG_NAME, O_CREAT | O_RDWR, 0666, &mq_attribute);
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024*1024);
long start_arg = 0; //the start argument is unused right now
pthread_create(&ATM, NULL, run_ATM, (void*) start_arg);
pthread_create(&DB_server, NULL, run_DB, (void*) start_arg);
pthread_join(ATM, NULL);
pthread_join(DB_server, NULL);
}
The receiving buffer is larger than the message queue size, so there should be no issues, right?
Upvotes: 0
Views: 1067
Reputation: 1307
So it looks like the main issue was with a leftover message queue, since they are not properly closed/unlinked in the code.
There were some bugs in my original code, and I appreciate the answers that pointed that out and gave me solutions.
The issue comes when trying to change the format of the message, I guess when mq_open
is called again, it doesn't change the message size (since the message queue already exists). This leads to size errors in the code. Rebooting is a workaround, but the solution is to properly clean up with mq_unlink()
and then mq_close()
Upvotes: -1
Reputation: 182753
If you checked for error returns from functions and printed them, the error would be obvious. You are casting the values of accountNumber
and PIN
to pointers rather than casting their addresses. You want:
status = mq_send(PIN_MSG, (const char*) &accountNumber, MESSAGE_QUEUE_SIZE, 1);
status = mq_send(PIN_MSG, (const char*) &PIN, MESSAGE_QUEUE_SIZE, 1);
status = mq_receive(PIN_MSG, (char*) &received_acct_number, 100, NULL);
status = mq_receive(PIN_MSG, (char*) &received_PIN, MESSAGE_QUEUE_SIZE, NULL);
Note that there are still a lot of problems with our code, most notably the fact that you overrun these variables by not correctly processing their sizes. You can sort of fix that like this:
status = mq_send(PIN_MSG, (const char*) &accountNumber, sizeof (accountNumber), 1);
status = mq_send(PIN_MSG, (const char*) &PIN, sizeof (PIN), 1);
status = mq_receive(PIN_MSG, (char*) &received_acct_number, sizeof(received_acct_number), NULL);
status = mq_receive(PIN_MSG, (char*) &received_PIN, sizeof(received_PIN), NULL);
But really you should have some kind of message format and you should serialize your messages to and from that format.
Upvotes: 2