This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Sockets and threads


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]