shutdown() for dup'ed socket

shutdown() for dup'ed socket

Post by Michael D'Erri » Wed, 29 Dec 1993 16:18:07



Hello,

Suppose I've connected stdin and stdout to a socket
(or maybe this was done by inetd for me).  Now if I
want to gracefully terminate the program, should I
shutdown() BOTH stdin and stdout before closing them,
or only one?  Does it matter?

I'm asking this because I do a shutdown on both and
occasionally end up with sockets stuck in the FIN_WAIT_2
state (under Solaris 2.2 - so it could be a bug :).
This prevents me from binding to the socket again if
my server process dies.

Thanks for any help!

Michael D'Errico

 
 
 

shutdown() for dup'ed socket

Post by Doug Siebe » Sat, 01 Jan 1994 18:07:36



>Hello,
>Suppose I've connected stdin and stdout to a socket
>(or maybe this was done by inetd for me).  Now if I
>want to gracefully terminate the program, should I
>shutdown() BOTH stdin and stdout before closing them,
>or only one?  Does it matter?
>I'm asking this because I do a shutdown on both and
>occasionally end up with sockets stuck in the FIN_WAIT_2
>state (under Solaris 2.2 - so it could be a bug :).
>This prevents me from binding to the socket again if
>my server process dies.

shutdown(2) won't fix that, its caused by close()ing the socket with unsent
data in it that doesn't get sent (including the FIN's and other little TCP
controls needed to properly terminate the connection)  The fix is to set the
SO_LINGER option for the socket.  Use l_linger = 0 and l_onoff = 1.  The man
page will tell you l_linger is the amount of time to linger, but on most
Unixes (except for BSD 4.4 at least, I believe it was Chris Torek who mailed
me a response to a query I had about SO_LINGER a year or so ago and told me
this was fixed in 4.4) a non-zero linger time means "infinity".  Which means
your process locks up when trying to close() the socket's file descriptor, or
during _exit()!  Ack!

For the cleanest, bestest way to terminate a TCP connection (IMHO of course)
you want to set the SO_LINGER option as I described, then do a shutdown() when
you want to terminate the connection, wait a reasonable amount of time (where
reasonable is application dependant, I'd recommend a couple of seconds if you
are doing something like say sending "goodbye" to a user or process on the
other end over a fairly stable network, longer if you want to be more certain
the other side sees it) then you do a close() on all file descriptors that
reference that socket.  Only one shutdown() is needed, it sends a FIN (or
whatever, I don't know low level TCP) to the other end which will make the
other end know you've closed gracefully without losing any data.  A close
without the SO_LINGER option does essentially the same thing (but not exactly)
Then a couple seconds later you do the close(), which sends an RST, (reset
connection) to the other end, if its not closed down, this slams the door
shut.  If you for some reason have some data still unsent, too bad, it is
lost.

I'm thinking that if you did a one-way shutdown (shutdown for send, but not
receive) you could then do a select on the socket and wait for it to select
true for read and thereby wait until the other end sees your shutdown for
send and responds by shutting down its end.  This would provide a cleaner way
to terminate.  I don't know if this works though, I haven't tried it.  For
my purposes, the 5 second wait I use is long enough, if the user on the remote
end of my app doesn't see me say 'goodbye', it isn't a big deal, and if the
network is so bad they can't get a response in 5 seconds, they probably don't
want to be connected at that moment anyway, I still shutdown everything else
cleanly on my end so nothing is lost.


Kibo Turkey Greece Macedonia Perl Watcom Mason Clinton Illuminati Fnord Hastur

 
 
 

1. sockets dup()ed to stdin and stdout of a process

   I am posting this for a friend of mine who doesn't have access

   Is it possible to use dup() to assign a socket to be the input
*and* the output of a process? I did this (to a process which uses the
stdio functions like gets(), etc.), in the hopes of then using
select() in another program to know when this process wants to read
and when it wants to write. The reading works fine, especially when
the other process does no input. If the other process does read()s, it
works also. But if it uses gets(), it doesn't work (it hangs, etc.).
select() also thinks the connection is writable, even though the stuff
that the other process printf()ed before it issued the gets() hasn't
been seen on the other end yet. My question is: what am I missing?
What should I know about the stdio functions when they've been dup()ed
to a socket? What is the right way to write EOF to such a process?
Will this work, in general, or do I need two separate sockets, one for
input and one for output?  Any help will be greatly appreciated.


2. os2 Boot Manager and LILO

3. dup()'ed pipe()'s to stdio

4. HELP! PCMCIA modem interrupt trouble

5. 2.5.42, cciss, factor more dup'ed code (6 of 7)

6. how do you get mailx to accept a text typed at command line as message

7. 2.5.44 cciss factor dup'ed code

8. ufsdump

9. 2.5.44 cciss factor more dup'ed code

10. 2.5.43 cciss factor more dup'ed code

11. 2.5.41, cciss, factor dup'ed code (4 of 5)

12. can file streams be dup()'ed

13. 2.5.42, cciss, factor dup'ed code (5 of 7)