Thread: recv() malfunctioning in a pthread?

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    3

    recv() malfunctioning in a pthread?

    Hello -

    I've got a simple client and simple server setup going. Right now, my client uses send() twice: first to send a header, and then to send a request. I know that this functionality is working correctly (I'll explain later).

    On the server side, I started simple; just had a while(1) loop accepting new connections and then recv()'ing the two send()'s. This worked just fine, and I could pull all the data that was sent and print it out to ensure it was correct.

    However, to allow for multiple requests to be processed at once, I wanted to detach a new pthread for every connection I had incoming. So I did something like this:

    Code:
    void *processRequest (void* arg) {
       int socket = (int) arg;
       char buf1[100];
       recv(socket, buf1, 100, 0);
       char buf2[100];
       recv(socket, buf2, 100, 0);   // BLOCKS HERE
       close(socket);
       // Do stuff with the buffers here.
    }
    
    int main() {
       // Set up socket stuff here
       pthread_attr_t attr;
       pthread_attr_init(&attr);
       pthread_attr_setstacksize(&attr, 1024*1024);
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
       while(1) {
          int connection = accept(socket, null, null);
          pthread_t thread;
          pthread_create (&thread, &attr, processRequest, (void *) connection);
       }
    }
    As noted in the comment in the code above, the program gets stuck in the second recv() call when I use pthreads. I've got no idea why. Does anyone have any suggestions?

    Thanks.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    How big is the header and how big is the payload? You are prob. reading both wth the first recv.

    gg

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    I don't see anything wrong that would cause this to stop working just because you started using threads. A few things though:

    Don't cast the "connection" descriptor to void * to pass it to the thread function. Casting between integer and pointer types works on some platforms but not everywhere. Going from int to void * to int again could lose information. Instead you should be passing an address of some kind. Allocate a little buffer to store the connection number and pass a pointer to that instead. Do NOT just pass a pointer to the connection variable itself. It might get overwritten by an immediately following connection before the first thread gets a chance to extract its value. In other words, that's a race condition.

    You also don't check the return value of recv(). The call to recv() is not guaranteed to actually return 100 bytes -- it could return less. It may require multiple calls to read all the data. Alternately you could pass MSG_WAITALL to try to read all the bytes in one call, but it still might error. You have to check.

    And why do these very simple threads need a 1 megabyte stack?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > my client uses send() twice: first to send a header, and then to send a request.
    But there's no reason for the receiver to see that division.

    It's like reading a file, you have no idea how the file was written (a byte at a time, a line at a time). All you see is a stream of bytes, and that's it.

    For recv(), it might take one call to get all the data, it might take 3 or 4. Even if it takes 2 calls, there's no reason to assume that it matches the packet sizes you sent.

    ALL the responsibility for parsing the stream rests with you. The network just transports it in packets which are convenient to transport, and reassembles the stream in the order it was sent.

    You should also be aware that send() doesn't guarantee to send the whole message in one call, so you need to pay close attention to that return result as well.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Nov 2007
    Posts
    3
    Thanks for the response, guys.

    t brewbuck: You are correct that I will need to eventually allocate for that int, I am still in the testing phase and I was sure that at least the part that passed the connection number was working fine.

    To all three of you, well, you were right in that I should be checking the value of recv(). However, I'm still a bit confused. The header is variable length unfortunately. It's a username and then an int to describe the size of the payload. More on this later.

    What is bothering me is the following: if I execute the two recv() calls directly from the while() loop, rather than creating a thread, the first recv() returns 9 bytes and the second recv() returns 50. If I do this in the pthread instead, the first returns 59 bytes (and as Codeplug mentioned, this is both send()'s which is why it is blocking).

    I guess I was incorrect in thinking that each recv() would only process the output from one send(); whoops. However, since this is the case, do either of you have any parsing suggestions? Since we can see from running directly in the while() loop it appears there is no guarantee both packets have been sent by the time I call the first recv(), I'm not sure how to decide whether or not I need a second recv(). And because the header isn't fixed length I don't know how to tell recv() ONLY to pull the data from the header with the first call.

    Yick...

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    The client typically needs to know how much data it can expect to recieve. Since the header is variable length, then the first member of the header could be "size of header".

    Then you just need functions for "send till it's sent" and "read till it's read"

    gg

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You need something in the data stream to tell you where the boundaries are.

    For example, HTML separates the header from the body with a blank line. In the first instance, you just accumulate data until that is seen (and save whatever comes after it for later), then parse the header.

    Another way is to prefix each message with a length, so you can read say 1 or 2 bytes initially, then know how many more to expect for the next 'frame' of data.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Nov 2007
    Posts
    3
    Ah, well admittedly this is a tiny, tiny bit of a school project that I'm working on. This recv() message problem had stumped me for more than 8 hours now (dumb, I know) so I'm glad you were able to assist on that. As far as the message headers, I can't really alter their structure as it's specified in the assignment, so that'll be a big pain in the rear. I'll slave away for a few more days and see if I can't get anything cranked out. Thanks for all of your help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Question about recv
    By carrotcake1029 in forum Networking/Device Communication
    Replies: 2
    Last Post: 02-26-2009, 02:10 PM
  2. Pthread recv Blocks
    By scioner in forum C Programming
    Replies: 6
    Last Post: 03-13-2008, 08:45 PM
  3. The Pthread Hell
    By matott in forum Linux Programming
    Replies: 1
    Last Post: 04-10-2005, 05:59 AM
  4. recv()
    By afisher in forum Networking/Device Communication
    Replies: 3
    Last Post: 03-24-2004, 05:32 PM
  5. non blocking recv
    By rohit in forum Linux Programming
    Replies: 4
    Last Post: 03-05-2002, 09:35 PM