Question

I am writing a POP3 server, and for some strange reason, it is only working on my computer and nobody else's. It simply exited with the error "Transport endpoint is not connected". Google shows that most problems with the same error message are caused by passing the socket id instead of the connection id to read, but I did nothing of the sort, and I actually made the point to check that they are different, which is true every time I try to run it.

void pop_protocol(int connection_descriptor){
    pthread_t tid;
    pthread_create(&tid, NULL, pop_worker, (void *) &connection_descriptor);
}

void *pop_worker(void *cd) {
    int connection_descriptor = *((int *) cd);
    socket_write(connection_descriptor, "+OK POP3 server ready\r\n");
}

int sockfd = socket_setup(portno);
while (1) {
    int connection = socket_get_new_connection(sockfd);
    pop_protocol(connection);
}

int socket_setup(int portno){
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1) {
        fprintf(stderr, "Error: Cannot create socket\n");
        perror("");
        exit(1);
    }

    struct sockaddr_in address;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_family      = AF_INET;
    address.sin_port        = htons(portno);

    if (bind(fd, (struct sockaddr *) &address, sizeof(address)) == -1) {
        fprintf(stderr, "Error: Cannot bind socket to port %d\n", portno);
        perror("");
        exit(1);
    }

    if (listen(fd, MAXCONNECTION) == -1) {
        fprintf(stderr, "Error: Cannot listen on port\n");
        perror("");
        exit(1);
    }

    return fd;
}

int socket_get_new_connection(int sockfd){
    struct sockaddr_in address;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    int new_socket = -1;
    int count = 0;
    while (new_socket < 0 && count < ACCEPTCOUNTER) {
        new_socket = accept(sockfd, (struct sockaddr *) &address, &addrlen);
    }

    // Attempt timed out. Exit
    if (count == ACCEPTCOUNTER) {
        fprintf(stderr, "Error: Cannot accept new connections");
        perror("");
        exit(1);
    }

    return new_socket;
}

I will be very grateful if anyone can offer any insight into the problem.

Was it helpful?

Solution

You pass a pointer to a local variable (parameter connection_descriptor) to a new thread. By the time the thread is created and executed, the pop_protocol function most probably returns, and the local variable is not valid any more (in fact, its value can still exist at the address that was passed to the new thread, but it's undefined behaviour.)

Try allocating memory for the connection_descriptor with malloc, passing that memory (not a local variable!) to the thread being created, and free that memory inside the thread's function after the socket id is copied into a local variable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top