netdev
[Top] [All Lists]

PROBLEM: a local TCP socket close does not trigger a poll on the other e

To: netdev@xxxxxxxxxxx
Subject: PROBLEM: a local TCP socket close does not trigger a poll on the other end
From: "Bernard MAUDRY" <support@xxxxxxxxxxxxx>
Date: Sat, 3 Mar 2001 11:49:12 +0100
Sender: owner-netdev@xxxxxxxxxxx
Dear sirs,

[1.] A local TCP socket close does not trigger a poll on the other end
[2.] The steps are :
      a  client connection is established with a local server
      in the client, a poll is made to detect the end of the communication
      after some data transfert has been done, the server closes its socket side
      in the client, the poll call does not indicate the end of the 
communication
      and can wait for a long time (more than 100 seconds, but may-be for ever)
[3.] TCP socket layer in kernel
[4.] Linux version 2.2.5-15 and 2.2.17-21mdk
[5.] no Oops
[6.] Program showing the problem
On my Linux machines, the following program displays:
  Communication OK
  Socket closed, polling peer ...
  The peer is not informed that the socket is closed ???

where it should display :
  Communication OK
  Socket closed, polling peer ...
  Socket OK

/* Beginning of the test case */
#include <sys/types.h>         /* needed by sys/socket.h and netinet/in.h */
#include <sys/socket.h>        /* for AF_INET, SOCK_STREAM, ... */
#include <sys/ioctl.h>         /* for FIONCLEX, FIONBIO, ... */

#ifndef FIOCLEX
#include <sys/filio.h>         /* for FIONCLEX, FIONBIO, ... */
#endif
#include <netinet/in.h>        /* struct sockaddr_in */
#include <poll.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <stropts.h>

#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif

int main (int argx, char ** argv)
{
    int ServerSocket;
    int ClientSocket;
    int AcceptedSocket;
    struct sockaddr_in  sin;
    struct hostent *hp;
    char HostName[255];
    int ON = 1 ;
    int OFF = 0 ;
    struct sockaddr_in  from;
    int    len = sizeof (from);
    int    Status;
    int    Result;
    struct pollfd Fds[1] ;

    /* Setup server socket */
    ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
    bzero((char *)&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;

    sin.sin_port = 10150;

    (void)setsockopt(ServerSocket, SOL_SOCKET, SO_REUSEADDR, (char 
*)&ON, sizeof (int));
    Status = bind(ServerSocket, (struct sockaddr *)&sin, sizeof(sin)) ;
    if (Status != 0)
    {
        printf ("Bind failed\n") ;
        exit (1) ;
    }
    Status = listen(ServerSocket, 5) ;
    (void)ioctl(ServerSocket, FIOCLEX, 0);
    (void)ioctl(ServerSocket, FIONBIO, &ON);

    /* Setup client socket */
    (void) gethostname(HostName, sizeof (HostName));
    hp = gethostbyname(HostName);
    sin.sin_family = AF_INET;
    bcopy((char *)hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
    sin.sin_port = 10150;

    ClientSocket = socket(AF_INET, SOCK_STREAM, 0);
    (void)setsockopt(ClientSocket, SOL_TCP, TCP_NODELAY, (char *)&ON, 
sizeof (int));
    (void)ioctl(ClientSocket, FIONBIO, &ON);
    (void)connect(ClientSocket, (struct sockaddr *)&sin, sizeof(sin)) ;

    /* Setup accepted socket */
    AcceptedSocket = accept(ServerSocket, (struct sockaddr *)&from, &len);
    (void)setsockopt(AcceptedSocket, SOL_TCP, TCP_NODELAY, (char 
*)&ON, sizeof (int));
    (void)ioctl(ClientSocket, FIONBIO, &OFF);

    /* Wait for the connection to be established */
    sleep (1) ;

    /* Verify the communication */
    write(ClientSocket, &ON, 4) ;
    Result = 0 ;
    read(AcceptedSocket, &Result, 4) ;
    if (Result != 1) printf ("Bad socket\n") ;
    else printf ("Communication OK\n") ;

    /* Close the accepted socket */
    Status = close(AcceptedSocket) ;

    printf ("Socket closed, polling peer ...\n") ;
    Fds[0].fd = ClientSocket ;
    Fds[0].events = 0 ;
    Status = poll(Fds, 1, 10000) ;

    if (Status == 0)
    {
        printf ("The peer is not informed that the socket is closed ???\n") ;
    }
    else printf ("Socket OK\n") ;

    /* Close remaining sockets */
    Status = close(ClientSocket) ;
    Status = close(ServerSocket) ;
}
/* End of the test case */


What should I do to get the expected behavior (work-around)?
Or do you have a fix for this bug?

Thanks for your help.

Bernard.

+--------------------------------------+
|  Bernard MAUDRY                      |
|  Top Graph'X Customer Support        |
|  10, allee de la mare Jacob          |
|  91290 La Norville                   |
|  FRANCE                              |
|  Tel: (33) 1 69 26 97 88             |
|  Fax: (33) 1 69 26 97 89             |
|  email: support@xxxxxxxxxxxxx        |
+--------------------------------------+

<Prev in Thread] Current Thread [Next in Thread>