Search code examples
csocketsudpsegmentation-faultrecv

Segmentation fault on recv() of socket.h


I got a strange segmentation fault when executing recv() function of . Here's the function used recv() in my code.

void* recv_and_update(void* t) 
{
    int tid = (int) t;
    int sockfd;
    struct sockaddr_in addr;
    int numbytes;
    char buf[BUFLEN];
    int flag = 1, len = sizeof(int);

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        printf("Failed to create socket on thread %d.\n", tid);
        exit(-1);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons( node.port );
    addr.sin_addr.s_addr = htonl( INADDR_ANY );

    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len);

    printf("start binding.\n");

    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)))
    {
        printf("Failed to bind socket on thread %d.\n", tid);
        exit(-1);
    }

    printf("binding finished.\n");

    while (1) 
    {
        printf("start recv()\n");

        if ((numbytes = recv(sockfd, buf, BUFLEN, 0)) < 0)
        {
            printf("Failed to receive msgs on thread %d.\n",
                    tid);
            exit(-1);
        }

        printf("end recv(), numbytes=%d\n", numbytes);
        buf[numbytes] = '\0';
        pthread_mutex_lock(&mutex);
        translate_and_update(buf);
        pthread_mutex_unlock(&mutex);
    }

    close(sockfd);
    pthread_exit(NULL);
}

The most weird part of this problem is that the segmentation fault doesn't happen every time. Usually after 100 or 200 times of receiving ( or less times occasionally ). And when it happens, the program would only output my "start recv()" sentence without "end recv()".

So I think the problem happens right in the recv() function, but I failed to figure out why and how to fix this.


Solution

  • From your discription it looks like recv() is blocking and the app crashes due to an error at a different location, will say in a different thread.

    Nevertheless buf is declared one byte too small.

    If having read BUFLEN bytes numbytes will be BUFLEN and the following call will write to memory not being allocated to be buf:

    buf[numbytes] = '\0';
    

    To fix this change

    char buf[BUFLEN];
    

    to be

    char buf[BUFLEN + 1];