AerRayes
AerRayes

Reputation: 69

Message Queue keeps sending/recieving garbage

In my assignment I have to fork processes to simulate a distributed operating system with process allocating using Heuristic Algorithm On Linux using IPC.

Now I fork n children and then make them simulate the algorithm, that's not the problem though the problem is in the message queue connections between all of them

There is 2 message queues UP and DOWN they are both not working atm. Every time I try to send something over any of these queues they are received at the other side as garbage.

So, I use this struct and those methods for dealing with message queue

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
struct msgbuff
{
   long mtype;
   char mtext[70];
};

void Send(key_t msgqid,char* S,long pid)
{
  int send_val;
  struct msgbuff message;

  message.mtype = pid;      /* arbitrary value */
  strcpy(message.mtext,S);
  cout<<"Message is "<<message.mtext<<endl;
  //strcpy(message.mtext, str);
  cout<<getpid()<<" Entering Send process"<<endl;
  send_val = msgsnd (msgqid, &message, sizeof(message), IPC_NOWAIT);

  if(send_val == -1)
    perror("Error in send");

}

char* Recieve(key_t msgqid,bool nowait)
{
        int rec_val;
          struct msgbuff message;

          cout<<getpid()<<" Entering Receive process"<<endl;
          /* receive all types of messages */
          if(nowait)
  rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), IPC_NOWAIT);  
  else rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), !IPC_NOWAIT);  
  if(rec_val == -1){
//      perror("Error in receive");
    return "none";
}
  return message.mtext;
}

Then I use them at every child like so

        DOWN = msgget(200, IPC_CREAT|0644);
        UP = msgget(201,IPC_CREAT|0644);

And

 while(1)
            {
                int countfail =0;
                char* ask =Recieve(DOWN,true); //nowait
                string asks(ask);
                cout<<getpid()<<" ask= "<<asks<<endl; //This here prints either garbage (symbols and other random characters) or "none"
                if(strcmp(ask,"none")!=0)
                {
                           ///////Logic for the algorithm
                    cout<<"*********"<<getpid()<<" In ASK "<<endl;
                    stringstream ss1;
                    ss1.str(ask);
                    int senderpid=0,processSize=0;
                    ss1>>processSize>>senderpid;
                    char* processRecMessage = new char[70];

                              ///setting up what will be sent to other process
                    if(count+ processSize <= load)
                    {
                        count+=processSize;
                        strcpy(processRecMessage,"Taken");

                    }
                    else
                    {
                        strcpy(processRecMessage,"Not Taken");
                    }

                           //Another Garbage here
                    Send(UP,processRecMessage,senderpid);



                }
                else{
                    int nextProcess = (rand()%3) +1;
                    if(count + nextProcess <=load)
                    {
                        count +=nextProcess;
                    }
                    else{

                        for(int k = 0;k<3;k++)
                        {
                            int selectedChild = rand()%n;
                            cout<<getpid()<<" Selected Child no "<<selectedChild+1<<" PID="<<children[selectedChild]<<endl;
                            char* x = new char[70];
                            stringstream ss;
                            ss<<nextProcess;
                            ss<<" "<<getpid();
                            strcpy(x,ss.str().c_str());// x= "nextProcess pid" 
                            cout<<x<<endl;
                 //// sending here also recieves garbage
                            Send (DOWN , x,children[selectedChild]);
                //// receiving  garbage
                            x= Recieve(UP,false);
                            cout<<getpid()<<" UP Value = "<<x<<endl;
                            if (strcmp(x,"Taken")==0){
                                cout<<"Process sent from "<<getpid()<<" to "<<children[selectedChild]<<endl;
                                break;
                            }
                            else
                            {
                                countfail++;
                                printf("TRAIL #%d failed\n",countfail);

                            }

                        }
                        if(countfail==3)
                        {
                            cout<<"Algorithm failed to allocate process.\n";
                            cout<<"Terminating Process "<<getpid()<<endl;
                            break;
                        }
                    }
                }
            }

So If anyone could help me with this I would be grateful

p.s.: I delete all message queues after each fail run of the program so each time they start anew but still no use.

edit: Adding the full code

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <math.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <string.h>
#include <map>
#include <sstream>
#include <ctime>

using namespace std;


struct msgbuff
{
   long mtype;
   char mtext[70];
};


void Send(key_t msgqid,char* S,long pid)
{
  int send_val;
  struct msgbuff message;

  message.mtype = pid;      /* arbitrary value */
  strcpy(message.mtext,S);
  cout<<"Message is "<<message.mtext<<endl;
  //strcpy(message.mtext, str);
  cout<<getpid()<<" Entering Send process"<<endl;
  send_val = msgsnd (msgqid, &message, sizeof(message), IPC_NOWAIT);

  if(send_val == -1)
    perror("Errror in send");

}

char* Recieve(key_t msgqid,bool nowait)
{
        int rec_val;
          struct msgbuff message;

          cout<<getpid()<<" Entering Receive process"<<endl;
          /* receive all types of messages */
          if(nowait)
  rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), IPC_NOWAIT);  
  else rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), !IPC_NOWAIT);  
  if(rec_val == -1){
//      perror("Error in receive");
    return "none";
}
  return message.mtext;
}

int main()
{
    int n ;
    pid_t pid;
    key_t DOWN,UP;
    DOWN = msgget(200, IPC_CREAT|0644);//Creates new identifier
    UP = msgget(201,IPC_CREAT|0644);

        int shmid;
        shmid = shmget(50, 393216, IPC_CREAT|0644);
void *shmaddr;

  shmaddr = shmat(shmid, (void *)0, 0);
    printf("DOWN = %d\n", DOWN);
    printf("UP = %d\n", UP);
    cout<<"Please enter the number of machines "<<endl;
    cin>>n;
    int* children = new int[n];
    string pids;
    stringstream ss4;
    ss4<<n;
    string number = ss4.str();
    pids+=number;
    pids+=" ";
    for (int i=0;i<n;i++)
    {
         pid = fork();
         children[i]=pid;
         stringstream ss3;
         ss3<<pid;
         string pidstr=ss3.str();
         pids+=pidstr;
         pids+=" ";
        if (pid==0)
            break;
    }
    if (pid==-1) 
    cout<<"Error in fork" <<endl;

    else if (pid==0) // child 
    {
        sleep(1);
        DOWN = msgget(200, IPC_CREAT|0644);
        UP = msgget(201,IPC_CREAT|0644);
        //cout<<"Entering child process"<<endl;

        shmid = shmget(50, 393216, IPC_CREAT|0644);
        shmaddr = shmat(shmid, (void *)0, 0);
        char* pidsrec = new char[100];
        strcpy(pidsrec,(char*) shmaddr);
        stringstream sss;
        string spid(pidsrec);
        sss.str(spid);
        sss>>n;
        children = new int[n];
        for(int i =0;i<n;i++)
        {
            sss>>children[i];
            //cout<<getpid()<<"Child #"<<i<<" = "<<children[i]<<endl;
        }

        srand(getpid());
        int load = (rand()%10) +1;  // load of operating on this system from 1-10
        int count=0;
        while(1)
        {
            int countfail =0;
            char* ask =Recieve(DOWN,true); //nowait
            string asks(ask);
            cout<<getpid()<<" ask= "<<asks<<endl;
            if(strcmp(ask,"none")!=0)
            {
                cout<<"*********"<<getpid()<<" In ASK "<<endl;
                stringstream ss1;
                ss1.str(ask);
                int senderpid=0,processSize=0;
                ss1>>processSize>>senderpid;
                char* processRecMessage = new char[70];
                if(count+ processSize <= load)
                {
                    count+=processSize;
                    strcpy(processRecMessage,"Taken");

                }
                else
                {
                    strcpy(processRecMessage,"Not Taken");
                }
                Send(UP,processRecMessage,senderpid);



            }
            else{
                int nextProcess = (rand()%3) +1;
                if(count + nextProcess <=load)
                {
                    count +=nextProcess;
                }
                else{

                    for(int k = 0;k<3;k++)
                    {
                        int selectedChild = rand()%n;
                        cout<<getpid()<<" Selected Child no "<<selectedChild+1<<" PID="<<children[selectedChild]<<endl;
                        char* x = new char[70];
                        stringstream ss;
                        ss<<nextProcess;
                        ss<<" "<<getpid();
                        strcpy(x,ss.str().c_str());// x= "nextProcess pid" 
                        cout<<x<<endl;
                        Send (DOWN , x,children[selectedChild]);

                        x= Recieve(UP,false);
                        cout<<getpid()<<" UP Value = "<<x<<endl;
                        if (strcmp(x,"Taken")==0){
                            cout<<"Process sent from "<<getpid()<<" to "<<children[selectedChild]<<endl;
                            break;
                        }
                        else
                        {
                            countfail++;
                            printf("TRAIL #%d failed\n",countfail);

                        }

                    }
                    if(countfail==3)
                    {
                        cout<<"Algorithm failed to allocate process.\n";
                        cout<<"Terminating Process "<<getpid()<<endl;
                        break;
                    }
                }
            }
        }

    }
    else //parent
    {

    strcpy((char*) shmaddr,pids.c_str());
    }
    cout<<getpid()<<" GOODBYE"<<endl;
    return 0;
}

I try it with any number of processes and there is always garbage received at the receive end of the message queue

Upvotes: 0

Views: 1644

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409472

In your Receive function, when you do

return message.mtext;

you are returning a pointer to data allocated locally on the stack. This area of the stack will not be valid after the function returns, and hence the dereferencing the pointer will cause undefined behavior. Also, if you use this pointer after calling another function, that area of the stack will most likely have been overwritten by the other function.

Since you're using C++, why not return std::string? It will solve this problem.

Upvotes: 1

Related Questions