Sockets and threads

Neale.Ferguson@softwareAG-usa.com Neale.Ferguson@softwareAG-usa.com
Wed Jan 24 06:28:00 GMT 2001


I have a sample program which creates a socket, creates a thread, the
thread issues a blocking accept on the socket, meanwhile the main thread
(after a delay) closes the socket and waits for the spawned thread to
complete. On Sun the accept() returns with EBADF but on Linux it doesn't
return.

Sun is using its native libraries, Linux is using both 2.1.3 and
2.2.0 of glibc.

Is this a case of behavior undefined by any standard or is it a problem
with either the Sun or glibc implementation?

Here's the program:

#include <stdio.h>
#include <errno.h>
#include <memory.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>

int s;

static void*
wait_thread (void* arg)
{
    int sd;
    struct sockaddr_in sin;
    socklen_t l_sin = sizeof(sin);

    printf ("waiter thread: calling accept()...\n");
    fflush(stdout);
    memset(&sin,0, sizeof(sin));

    if ((sd = accept(s, (struct sockaddr *) &sin, &l_sin)) < 0)
        perror ("accept");

    printf ("waiter thread: returning...\n");
    fflush(stdout);
    return 0;
}

main ()
{
 unsigned flags;
 struct sockaddr_in sa;
 pthread_t tobject;
 int interval = 5;
 int tid;

    printf ("initializing...\n");

    /* initialize socket */
    if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        perror ("socket");
        return 0;
    }

    memset (&sa, 0, sizeof (sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons (3333);

    if (bind (s, (struct sockaddr *)&sa, sizeof (sa)))
    {
        perror ("bind");
        return 0;
    }

    if (listen (s, 1))
    {
        perror ("listen");
        return 0;
    }

    /* create waiter thread */
    printf ("creating waiter thread...\n");
    tid = pthread_create (&tobject, 0, wait_thread, 0);
    printf("tid: %d\n",tid);

    /* wait 2 seconds for waiter thread to initialize */
    if (sleep(interval))
    {
        perror ("sleep");
        return 0;
    }

    /* close the socket;  this should cause the waiter thread to return */
    printf ("closing socket...\n");
    close (s); perror("close");

    if (sleep(interval))
    {
        perror ("sleep");
        return 0;
    }

    /* wait for waiter thread to exit */
    printf ("waiting for waiter thread...\n");
    pthread_join (tobject, 0);

    printf ("done.\n");
}

Here's the Sun console log:

initializing...
creating waiter thread...
tid: 0
waiter thread: calling accept()...
closing socket...
accept: Bad file number
waiter thread: returning...
close: Error 0
waiting for waiter thread...
done.

Here's the Linux log:

initializing...
creating waiter thread...
tid: 0
waiter thread: calling accept()...
closing socket...
close: Interrupted system call
waiting for waiter thread...
<CTRL-C> required



More information about the Libc-alpha mailing list