How Can I call close() for all - Linux

This is a discussion on How Can I call close() for all - Linux ; I have a server application that uses a communication loop with a select to handle multiple clients. How Can I call close() for all the sockets currently open? (i.e., all the clients currently connected) Will that cause any sort of ...

+ Reply to Thread
Page 1 of 2 1 2 LastLast
Results 1 to 20 of 31

Thread: How Can I call close() for all

  1. How Can I call close() for all

    I have a server application that uses a communication loop
    with a select to handle multiple clients.

    How Can I call close() for all
    the sockets currently open? (i.e., all the clients currently
    connected) Will that cause any sort of trouble?


    What I want/need to do is to implement a mechanism to
    shutdown the server, so I'm wondering if I can just go
    through the list of the sockets and close them (well,
    maybe sending them a message first).


    Any advice highly appreciated. Thanks,


  2. Re: How Can I call close() for all

    sreyas.jose@wipro.com writes:

    >What I want/need to do is to implement a mechanism to
    >shutdown the server, so I'm wondering if I can just go
    >through the list of the sockets and close them (well,
    >maybe sending them a message first).


    Just iterate and call shutdown() and then close() on them all;
    if any of them are not open, or not sockets, the system calls will check
    and inform you through their exit status and errno.

    --
    Chris.

  3. Re: How Can I call close() for all

    Chris McDonald writes:
    > sreyas.jose@wipro.com writes:
    >
    >>What I want/need to do is to implement a mechanism to
    >>shutdown the server, so I'm wondering if I can just go
    >>through the list of the sockets and close them (well,
    >>maybe sending them a message first).

    >
    > Just iterate and call shutdown() and then close() on them all;


    The close alone should be sufficient.

  4. Re: How Can I call close() for all

    On Nov 27, 3:11 pm, Rainer Weikusat wrote:
    > Chris McDonald writes:
    > > sreyas.j...@wipro.com writes:

    >
    > >>What I want/need to do is to implement a mechanism to
    > >>shutdown the server, so I'm wondering if I can just go
    > >>through the list of the sockets and close them (well,
    > >>maybe sending them a message first).

    >
    > > Just iterate and call shutdown() and then close() on them all;

    >
    > The close alone should be sufficient.


    This is the code that I had written


    /* TcpServer.c - TCP server Code
    * This file implements the server-side functionality of the Client-
    Server
    * application.The code demonstrates the usage of socket routine
    calls.
    */

    /* includes */

    #include "vxWorks.h"
    #include "sockLib.h"
    #include "inetLib.h"
    #include "taskLib.h"
    #include "stdioLib.h"
    #include "strLib.h"
    #include "ioLib.h"
    #include "fioLib.h"
    #include "Tcp.h"

    /* function declarations */

    VOID tcpServerWorkTask (int sFd, char * address, u_short port);

    int tcpServer_close(void);

    /* Global Variable*/

    int serverStatus = FALSE;
    int sFd; /* socket file descriptor */

    /
    ************************************************** **************************

    * NAME : tcpSerevr
    *
    * INPUT : void
    *
    * DESCRIPTION : Accept and process requests over a TCP socket
    *
    * RETURNS : Never, or ERROR if a resources could not be allocated
    *

    ************************************************** ***************************/

    STATUS tcpServer (void)

    {

    struct sockaddr_in serverAddr; /* server's socket address */
    struct sockaddr_in clientAddr; /* client's socket address */
    int sockAddrSize; /* size of socket address structure */
    int sFd; /* socket file descriptor */
    int newFd; /* socket descriptor from accept */

    int ix = 0; /* counter for work task names */
    char workName[16]; /* name of work task */

    /* set up the local address */

    sockAddrSize = sizeof (struct sockaddr_in);
    bzero ((char *) &serverAddr, sockAddrSize);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_len = (u_char) sockAddrSize;
    serverAddr.sin_port = htons (SERVER_PORT_NUM);
    serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);

    /* create a TCP-based socket */

    if ((sFd = socket (AF_INET, SOCK_STREAM, 0)) == ERROR)

    {
    perror ("socket");
    return (ERROR);
    }


    /* bind socket to local address */

    if (bind (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) ==
    ERROR)

    {
    printf("%s",serverAddr);
    perror ("bind");

    close (sFd);
    return (ERROR);
    }

    /* create queue for client connection requests */

    if (listen (sFd, SERVER_MAX_CONNECTIONS) == ERROR)

    {
    perror ("listen");
    close (sFd);
    return (ERROR);
    }



    /* accept new connect requests and spawn tasks to process them */

    serverStatus = TRUE;

    while(serverStatus)

    {

    if ((newFd = accept (sFd, (struct sockaddr *) &clientAddr,

    &sockAddrSize)) == ERROR)

    {
    perror ("accept");
    close (sFd);
    return (ERROR);
    }

    sprintf (workName, "tTcpWork%d", ix++);

    if (taskSpawn(workName, SERVER_WORK_PRIORITY, 0, SERVER_STACK_SIZE,
    (FUNCPTR) tcpServerWorkTask, newFd,
    (int) inet_ntoa (clientAddr.sin_addr), ntohs
    (clientAddr.sin_port),
    0, 0, 0, 0, 0, 0, 0) == ERROR)

    {
    /* if taskSpawn fails, close fd and return to top of loop */
    perror ("taskSpawn");
    close (newFd);
    }
    }
    return(OK);
    }

    /
    ************************************************** *********************************
    *
    * NAME : tcpServerWorkTak
    *
    * INPUT : Server's socket fd, clients socket address and clients
    socket port
    *
    * DESCRIPTION : This routine reads from the server's socket, and
    processes client
    * requests
    *
    * RETURNS : N/A
    *

    ************************************************** **********************************/

    VOID tcpServerWorkTask

    (

    int sFd, /* server's socket fd */
    char * address, /* client's socket address */
    u_short port /* client's socket port */

    )

    {

    char * recv_strng;
    recv_strng = (char *)malloc(50);
    int nRead; /* number of bytes read */

    static char replyMsg[] = "Server received your message";

    /* read client request, display message */

    while ((nRead = fioRead (sFd, (char *) recv_strng, 50)) > 0)

    {

    recv_strng[11]= '\0';
    printf("\n\rnRead = %d", nRead);

    printf ("MESSAGE FROM CLIENT (Internet Address %s, port %d):\n%s\n",
    address, port, recv_strng);

    memset(recv_strng, 0, 50);


    if (write (sFd, (char *) recv_strng, sizeof (replyMsg)) == ERROR)
    {
    perror ("write");
    close (sFd);
    }

    if (nRead == ERROR) /* error from read() */
    perror ("read");
    close (sFd); /* close server socket
    connection */

    }
    }

    /
    ************************************************** *********************************
    *
    * NAME : tcpServer_close
    *
    * INPUT : void
    *
    * DESCRIPTION : Grace ful close of Server
    *
    * RETURNS : N/A
    *

    ************************************************** **********************************/

    int tcpServer_close(void)
    {
    int ret;
    serverStatus = FALSE;
    printf("closing the server");

    do
    {
    ret = close(sFd);
    }
    while (ret == -1 && errno == EINTR);
    return ret;
    }

    my doubt is if I cose like this whether all the clients that are
    connected to the server will close graceful or not..?

    Thanks in advance
    Sreyas


  5. Re: How Can I call close() for all

    sreyas.jose@wipro.com writes:

    > I have a server application that uses a communication loop
    > with a select to handle multiple clients.
    >
    > How Can I call close() for all
    > the sockets currently open? (i.e., all the clients currently
    > connected) Will that cause any sort of trouble?


    Not for the system. Whether it causes trouble for the clients depends
    on the clients...

    > What I want/need to do is to implement a mechanism to
    > shutdown the server, so I'm wondering if I can just go
    > through the list of the sockets and close them (well,
    > maybe sending them a message first).


    If all you want to do is make sure they're all closed, you can just
    stop your server. All open file descriptors are closed while a
    process is shutting down.

    If you want to send a message first, you can just go through all the
    file descriptors that have clients connected and send it. Presumably
    you're keeping track of them.


  6. Re: How Can I call close() for all

    sreyas.jose@wipro.com writes:
    >
    > my doubt is if I cose like this whether all the clients that are
    > connected to the server will close graceful or not..?


    That depends on the client, and what you mean by graceful. Next time
    they try to do IO on the socket, the call will fail. What happens
    next is up to the client.

  7. Re: How Can I call close() for all

    Rainer Weikusat writes:

    >Chris McDonald writes:
    >> sreyas.jose@wipro.com writes:
    >>
    >>>What I want/need to do is to implement a mechanism to
    >>>shutdown the server, so I'm wondering if I can just go
    >>>through the list of the sockets and close them (well,
    >>>maybe sending them a message first).

    >>
    >> Just iterate and call shutdown() and then close() on them all;


    >The close alone should be sufficient.



    Based on the wording of the original question, I was assuming that all
    *sockets* were to be closed, possibly not files, and my proposal was to
    shutdown() the sockets to first determine if they were sockets.

    Doesn't using shutdown() also expedite the tearing down between client
    and server?

    --
    Chris.

  8. Re: How Can I call close() for all

    On Nov 27, 2:11 am, Rainer Weikusat wrote:

    > > Just iterate and call shutdown() and then close() on them all;

    >
    > The close alone should be sufficient.


    No! This can cause *major* security problems. See my other post on the
    same subject.

    The basic problem is this:

    Thread A is about to write some security-sensitive data to a highly-
    trusted client connection. It is just about to call 'write'.

    Thread B calls 'close' on all the connections, including the one
    above.

    Thread C calls 'accept' and accepts a new, untrusted connection. It
    gets the same descriptor that thread A is about to write to and thread
    B closed.

    Thread A runs, sending the security-sensitive data to the untrusted
    client connection that has not received any other processing at all.

    Oops!

    DS

  9. Re: How Can I call close() for all

    On Nov 27, 8:17 am, Joe Pfeiffer wrote:
    > sreyas.j...@wipro.com writes:


    > That depends on the client, and what you mean by graceful. Next time
    > they try to do IO on the socket, the call will fail. What happens
    > next is up to the client.


    Sadly, it is not guaranteed that it will fail. It may succeed and do
    something very different from what you wanted.

    DS



  10. Re: How Can I call close() for all

    David Schwartz writes:

    > On Nov 27, 8:17 am, Joe Pfeiffer wrote:
    >> sreyas.j...@wipro.com writes:

    >
    >> That depends on the client, and what you mean by graceful. Next time
    >> they try to do IO on the socket, the call will fail. What happens
    >> next is up to the client.

    >
    > Sadly, it is not guaranteed that it will fail. It may succeed and do
    > something very different from what you wanted.


    Your comments in this thread have surprised me a lot -- my impression
    has always been that when one end of a socket connection goes away,
    the connection is broken. You've been saying (if I understand
    correctly) that another process can jump in and grab the port that is
    the server's end of the socket, and the client will find itself
    talking to the new process.

    I'm a bit confused as to how this can happen (before I go any further,
    please, if I misunderstood your previous posts, correct me!) -- after
    all, when a client connects to the server, a new randomly-numbered
    socket is created and the file descriptor returned from accept() is
    connected to this socket. How does a new process go about using this
    socket after the original server closes its connection? Does it
    bind() to it?

    Anyway, I'd be very interested in looking at some cites showing me how
    this is done....

  11. Re: How Can I call close() for all

    Chris McDonald writes:
    > Rainer Weikusat writes:
    >>Chris McDonald writes:
    >>> sreyas.jose@wipro.com writes:
    >>>
    >>>>What I want/need to do is to implement a mechanism to
    >>>>shutdown the server, so I'm wondering if I can just go
    >>>>through the list of the sockets and close them (well,
    >>>>maybe sending them a message first).
    >>>
    >>> Just iterate and call shutdown() and then close() on them all;

    >
    >>The close alone should be sufficient.

    >
    >
    > Based on the wording of the original question, I was assuming that all
    > *sockets* were to be closed, possibly not files, and my proposal was to
    > shutdown() the sockets to first determine if they were sockets.
    >
    > Doesn't using shutdown() also expedite the tearing down between client
    > and server?


    Quoting from socket(7):

    close(2) is used to close a socket. shutdown(2) closes parts
    of a full duplex socket connection.

    For Linux-TCP (IPv4), there is a difference wrt the handling of data
    that was received but not yet read by the application. A shutdown(fd,
    SHUT_WR) unconditionally causes a FIN to be sent, while a close in
    such a case would result in a RST.

  12. Re: How Can I call close() for all

    David Schwartz writes:
    > On Nov 27, 2:11 am, Rainer Weikusat wrote:
    >
    >> > Just iterate and call shutdown() and then close() on them all;

    >>
    >> The close alone should be sufficient.

    >
    > No! This can cause *major* security problems.


    [...]

    > The basic problem is this:
    >
    > Thread A is about to write some security-sensitive data to a highly-
    > trusted client connection. It is just about to call 'write'.
    >
    > Thread B calls 'close' on all the connections, including the one
    > above.
    >
    > Thread C calls 'accept' and accepts a new, untrusted connection. It
    > gets the same descriptor that thread A is about to write to and thread
    > B closed.
    >
    > Thread A runs, sending the security-sensitive data to the untrusted
    > client connection that has not received any other processing at all.


    Multithreaded code operating on shared ressources without proper
    serialization can behave in unexpected ways. Film at 11. Relevance
    regarding the question:

    I have a server application that uses a communication loop
    with a select to handle multiple clients.

    How Can I call close() for all
    the sockets currently open? (i.e., all the clients currently
    connected)

    or wrt the question if close can be used to close a TCP-connection or
    under which circumstances (unread data) a shutdown/ close sequence may
    be more appropriate: Zero.


  13. Re: How Can I call close() for all

    On Nov 27, 10:19 pm, Joe Pfeiffer wrote:

    > > Sadly, it is not guaranteed that it will fail. It may succeed and do
    > > something very different from what you wanted.


    > Your comments in this thread have surprised me a lot -- my impression
    > has always been that when one end of a socket connection goes away,
    > the connection is broken. You've been saying (if I understand
    > correctly) that another process can jump in and grab the port that is
    > the server's end of the socket, and the client will find itself
    > talking to the new process.


    No, that's not what I'm saying. What I am saying is that another
    socket can grab that same *descriptor* leading to code that was about
    to call 'write' on one connection to call 'write' for the same data
    but to a completely different connection.

    > I'm a bit confused as to how this can happen (before I go any further,
    > please, if I misunderstood your previous posts, correct me!) -- after
    > all, when a client connects to the server, a new randomly-numbered
    > socket is created and the file descriptor returned from accept() is
    > connected to this socket. How does a new process go about using this
    > socket after the original server closes its connection? Does it
    > bind() to it?


    You are confusing descriptors and the connection endpoints they refer
    to. Ports are randomly-numbered, descriptors are always assigned the
    lowest available non-negative integer.

    > Anyway, I'd be very interested in looking at some cites showing me how
    > this is done....


    Thread A is about to call 'write' on descriptor 3 which refers to a
    connection to a trusted source.

    Thread B calls 'close' for descriptor 3.

    Thread C calls 'accept' and a new connection to an untrusted source
    gets descriptor 3 since it's the lowest available descriptor.

    Thread A writes the sensitive data to the untrusted source. Ooops.

    DS

  14. Re: How Can I call close() for all

    On Nov 28, 4:09 am, Rainer Weikusat wrote:

    > Multithreaded code operating on shared ressources without proper
    > serialization can behave in unexpected ways. Film at 11. Relevance
    > regarding the question:
    >
    > I have a server application that uses a communication loop
    > with a select to handle multiple clients.
    >
    > How Can I call close() for all
    > the sockets currently open? (i.e., all the clients currently
    > connected)
    >
    > or wrt the question if close can be used to close a TCP-connection or
    > under which circumstances (unread data) a shutdown/ close sequence may
    > be more appropriate: Zero.


    You are, again, dangerously wrong. I swear, sometimes it seems like
    you try to give people dangerously bad advice. I warn people about bad
    things for good reasons, and you always want them to ignore the
    warnings. What is up with that?!

    Consider:

    1) You call 'select' and get a list of sockets to process.

    2) The first socket you process contains a command that tells the
    server shut down, so you call 'close' on all your connections.

    3) You call 'syslog' to log the fact that you are shutting down.
    Unbeknowst to you, 'syslog' opens a TCP connection to write the log
    event. (You neither know nor care how 'syslog' works its magic.) The
    socket is left open in case there are further log entries.

    4) You continue processing the list you got from 'select' because you
    only check for shutdown at the top of the loop. You go to the next
    socket (whose descriptor now refers to the log socket) and write some
    sensitive data that should not go in the log to that connection.

    Same problem. Calling 'close' without logically shutting down the
    connection in your program logic is dangerous. The OP is asking if he
    can blindly 'close' sockets and the answer is *NO*, you must "spin
    them down" in your program logic first.

    DS

  15. Re: How Can I call close() for all

    David Schwartz writes:
    > On Nov 28, 4:09 am, Rainer Weikusat wrote:
    >> Multithreaded code operating on shared ressources without proper
    >> serialization can behave in unexpected ways. Film at 11. Relevance
    >> regarding the question:
    >>
    >> I have a server application that uses a communication loop
    >> with a select to handle multiple clients.
    >>
    >> How Can I call close() for all
    >> the sockets currently open? (i.e., all the clients currently
    >> connected)
    >>
    >> or wrt the question if close can be used to close a TCP-connection or
    >> under which circumstances (unread data) a shutdown/ close sequence may
    >> be more appropriate: Zero.


    [...]

    > Consider:
    >
    > 1) You call 'select' and get a list of sockets to process.
    >
    > 2) The first socket you process contains a command that tells the
    > server shut down, so you call 'close' on all your connections.
    >
    > 3) You call 'syslog' to log the fact that you are shutting down.
    > Unbeknowst to you, 'syslog' opens a TCP connection to write the log
    > event. (You neither know nor care how 'syslog' works its magic.) The
    > socket is left open in case there are further log entries.
    >
    > 4) You continue processing the list you got from 'select' because you
    > only check for shutdown at the top of the loop. You go to the next
    > socket (whose descriptor now refers to the log socket) and write some
    > sensitive data that should not go in the log to that connection.
    >
    > Same problem.


    Exactly. This is still an application programming error and bears no
    relation to the behaviour of certain system calls for certain types of
    arguments.


  16. Re: How Can I call close() for all

    On Nov 28, 8:15 am, Rainer Weikusat wrote:

    > Exactly. This is still an application programming error and bears no
    > relation to the behaviour of certain system calls for certain types of
    > arguments.


    Read the OP's question again.

    If a person asks, "can I load a gun and point at my head", and someone
    says, "don't do that, it could go off and kill you", you'd be right
    there to reply that "actually, loading a gun and pointing it at
    someone's head is perfectly safe, the question had nothing to do with
    triggers".

    DS

  17. Re: How Can I call close() for all

    David Schwartz writes:
    >
    > > Anyway, I'd be very interested in looking at some cites showing me how
    > > this is done....

    >
    > Thread A is about to call 'write' on descriptor 3 which refers to a
    > connection to a trusted source.
    >
    > Thread B calls 'close' for descriptor 3.
    >
    > Thread C calls 'accept' and a new connection to an untrusted source
    > gets descriptor 3 since it's the lowest available descriptor.
    >
    > Thread A writes the sensitive data to the untrusted source. Ooops.


    This breakage (and I'll agree it's dangerously broken) has nothing to
    do with calling close() on the file descriptor, it's a multithreaded
    application that isn't keeping track of its own state. If Thread B is
    closing a descriptor without Thread A knowing about it, it's a pretty
    desperately mis-written piece of code.

  18. Re: How Can I call close() for all

    David Schwartz writes:
    > On Nov 28, 8:15 am, Rainer Weikusat wrote:
    >
    >> Exactly. This is still an application programming error and bears no
    >> relation to the behaviour of certain system calls for certain types of
    >> arguments.

    >
    > Read the OP's question again.


    ,----
    | I have a server application that uses a communication loop
    | with a select to handle multiple clients.
    |
    | How Can I call close() for all
    | the sockets currently open? (i.e., all the clients currently
    | connected) Will that cause any sort of trouble?
    `----

    There is no further information regarding the application and the
    question clearly refers to 'currently connected clients' and if it is
    ok to close the sockets representing the respective TCP-connection.

    And it is ok to close the sockets (If either none of them has
    unreceived data sitting in its recv buffer or the clients are expected
    to tolerate a RST for connection termination).

    > If a person asks, "can I load a gun and point at my head",
    > and someone says, "don't do that, it could go off and kill you",


    The you can imagine a lot of buggy applications which close file
    descriptors they use without stopping to use them afterwards is
    neither a sufficient reason to assume that the application the
    question was refering to is such a buggy application relying on
    descriptor numbers remaining invalid across a close followed by an
    open (of some kind) nor does it (repeated for the third time) anyhow
    relate to wether a file descriptor refering to a TCP-connection can
    just be closed if the TCP-connection is supposed to be terminated.

    No matter what logical connection teardown processing an application
    may implement or would need to implement, it still needs to close the
    descriptor at some point to inform the kernel that this particular
    connection is supposed to be dead from now on.

  19. Re: How Can I call close() for all

    David Schwartz writes:

    > On Nov 28, 8:15 am, Rainer Weikusat wrote:
    >
    > > Exactly. This is still an application programming error and bears no
    > > relation to the behaviour of certain system calls for certain types of
    > > arguments.

    >
    > Read the OP's question again.
    >
    > If a person asks, "can I load a gun and point at my head", and someone
    > says, "don't do that, it could go off and kill you", you'd be right
    > there to reply that "actually, loading a gun and pointing it at
    > someone's head is perfectly safe, the question had nothing to do with
    > triggers".


    No... it's more as if somebody asked "can I go trap shooting", and
    getting an answer like "no, because you might point the gun at your
    head and pull the trigger".

  20. Re: How Can I call close() for all

    On Nov 28, 11:09 am, Joe Pfeiffer wrote:

    > This breakage (and I'll agree it's dangerously broken) has nothing to
    > do with calling close() on the file descriptor, it's a multithreaded
    > application that isn't keeping track of its own state. If Thread B is
    > closing a descriptor without Thread A knowing about it, it's a pretty
    > desperately mis-written piece of code.


    Right, so the answer to the OP is, "no, you can't call 'close' blindly
    on a whole bunch of descriptors". There are a hundred ways to screw up
    by calling 'close' before you cleanly shut down the application state
    associated with the connection. This has to be done to each descriptor
    separately, and you might as well call 'close' when you finish that
    process. So, again, *no*, you can't just call 'close' on a whole bunch
    of descriptors.

    DS

+ Reply to Thread
Page 1 of 2 1 2 LastLast