0
votes

Part of this assignment I'm working on involves a program that executes commands from a client via a socket. Now the only file I have to edit is my mathServer.c I'm currently stuck on one of the several parts from the instructions provided:

Finish the method - doServer(). doServer() should have a loop in which it waits for a client to connect to listenFd. When a client does, it should:

  1. malloc() enough memory for 2 integers

  2. put the file descriptor from accept() in one of those spaces

  3. put the value of threadCount in the other space, and increment threadCount

  4. Make a detached thread to handle this new client. I called my function handleClient(), but you may call yours whatever. Pass the address of your malloc()-ed array.

The loop should then go back for another accept().

Here's my doServer:

void doServer (int listenFd)
{
  //  I.  Application validity check:

  //  II.  Server clients:
  pthread_t     threadId;
  pthread_attr_t    threadAttr;

  int   threadCount = 0; 

  // YOUR CODE HERE
  int *a;

  while(1) {

    //1. If Malloc was NEVER (outside or inside loop) in this program then 
    // it outputs Thread 0 recieved
    a = malloc(sizeof(int) * 2);

    accept(getServerFileDescriptor(), NULL, NULL);

    // 2.
    a[0] = getServerFileDescriptor();

    // 3.
    a[1] = threadCount++;

    // ALL 4
    pthread_attr_init(&threadAttr);
    pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
    pthread_create(&threadId, &threadAttr, handleClient, &a);

    pthread_join(threadId, NULL); 
    pthread_attr_destroy(&threadAttr);

   }

}

Here's my handleClient method:

void* handleClient(void* vPtr) {

  // Use another pointer to cast back to int*
  // Save the file descriptor and thread number in local vars
  // free() the memory

  // I wrote these 2 lines.
  int *castMe = (int *)vPtr;
  free(vPtr);

  //  II.B.  Read command:
  char  buffer[BUFFER_LEN];
  char  command;
  int fileNum;

  int fd = castMe[0];
  int threadNum = castMe[1];

  char  text[BUFFER_LEN];
  int   shouldContinue  = 1;

  while  (shouldContinue)
  {
    text[0] = '\0';

    read(fd,buffer,BUFFER_LEN);
    printf("Thread %d received: %s\n",threadNum,buffer);
    sscanf(buffer,"%c %d \"%[^\"]\"",&command,&fileNum,text);

    //printf("Thread %d quitting.\n",threadNum);
    return(NULL);

    // YOUR CODE HERE

  }

}

I've discovered whenever I remove a = malloc(sizeof(int) * 2) and everything associated with malloc it does output Thread 0 received. However, when I keep malloc the output is just blank and will not return anything.

At first I thought it was because I didn't free the memory, but the memory is being freed from handleClient correct?

**please note this is not the whole program. Any methods you see here are the professors work. these two methods are my own (your code here). Just assume the professors code works :) **

Any help is much appreciated!

4

4 Answers

1
votes

Your piece of code

// I wrote these 2 lines.
int *castMe = (int *)vPtr;
free(vPtr);

free the memory pointed by castMe and when you use it you are dereferencing to non valid memory

int fd = castMe[0];       //<----- BOOM
int threadNum = castMe[1];//<----- BOOM

It is undefined behavior

Moreover when you wrote I remove a = malloc(sizeof(int) * 2) I guess you leave a declaration as is

int *a;

That is undefined behavior because of a is not pointing to a valid memory address.

0
votes

Here's the bug:

int *castMe = (int *)vPtr;
free(vPtr);
...
int fd = castMe[0];

You deallocate the memory that vPtr points at and then later on attempt to access that memory through another pointer.

0
votes

This:

pthread_create(&threadId, &threadAttr, handleClient, &a);
                                                     ^
                                                     |
                                                    WAT

Is a problem, since here you make the pthreads library pass the address of the pointer to the first element in a to the thread, where you meant to pass just a pointer to the first element in a.

So, you should have passed &a[0], which is more easily and clearly written as just a.

This call doesn't match how you then use the argument inside the thread function. You can print the two to see the difference:

printf("&a=%p\n", (void *) &a);

and then in the function add:

printf("castMe=%p\n", (void *) castMe);

The values will be different.

Also, your memory handling is off, never free() data that you still need. And in C you don't need explicit casts to/from data pointers and void *, you can just do:

int * const numbers = vPtr;
0
votes

is this answered? I am working on this too!