netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Geoffrey Lee <glee@gnupilgrims.org>
To: kuznet@ms2.inr.ac.ru
Cc: netdev@oss.sgi.com
Subject: Re: [PATCH] connect() return value.
Date: Tue, 13 Aug 2002 12:21:15 +1000	[thread overview]
Message-ID: <20020813022115.GA11627@anakin.wychk.org> (raw)
In-Reply-To: <200208120128.FAA16791@sex.inr.ac.ru>

On Mon, Aug 12, 2002 at 05:28:38AM +0400, kuznet@ms2.inr.ac.ru wrote:
> Hello!
> 
> >					     I wanted to know what 
> > is the "correct" behavior for connect() by default with signal().
> 
> This simply does not matter, that's answer.
> 
> Actually, it is not so easy to implement restartable connect().
> I think this is the only reason why it not restartable in some OSes.
> 


True, probably.

Solaris will not restart a connect() even with the SA_RESTART set
in sa_flags.


> BTW could you make the following experiments on the same OSes:
> connect() on nonblocking socket, then repeat the connect()
> until it returns EISCONN. I guess the behaviour also will be different.
> 
> 



In brief, it is what we expect. After we do a connect() on a
non-blocking socket, it returns -EINPROGRESS. On subsequent
attempts it returns -EALREADY, then after it is connected
it returns -EISCONN. This behavior is consistent in all operating
systems which I have tested, which include the following:

Digital UNIX (OSF1 4.0)
Solaris (SunOS 5.6)
Linux (2.4.18)



On a LAN, when we run the program on first try, it is usually possible
to see -EINPROGRESS, -EALREADY, then -EISCONN. On subsequent
runs it normally returns -EINPROGRESS, then -EISCONN. This 
behavior can be explained by arp interaction and is consistent
with what we expect. 

On a WAN link, we see it return -EINPROGRESS, -EALREADY, then
-EISCONN all of the time.

Not tested on BSD yet, but I expect the results to be consistent
with my current findings. I can post the results later if you 
want them.

This is all fine, but what is interesting is what follows aftewards.
It was noted in Richard Steven's UNIX Network Programming that there are
several ways which you could find out to see if the connection has
succeeded in the background. One way mentioned is to call a read()
with a length of 0. With this method, it implies that read() must return
an error for an in-progress socket, otherwise there would be no way to
distinguish between a in-progress socket or a completed socket. To test
this, we write a program to connect to a open TCP port on a remote machine
on the WAN (to maximize the delay).

We set the socket to non-blocking then we issue a TCP connect(). 
connect() will return immediately while the connection is attempted
in the background asynchroniously. After the return from connect() 
we immediately issue a read() with a length of 0, and we note the
return value from read, the errno (if applicable). Finally, we issue
a second connect() and we note the return value, and errno (if 
applicable).

This is what happens on Digital UNIX (OSF1 4.0):

read() returns 0 with an errno of 36. 36 on Digital UNIX corresponds to
-EINPROGRESS. The errno isn't from the read but from our first
connect(). On second connect(), it returns -1, with an errno of
-EALREADY.

On Solaris (SunOS 5.6):

read() returns -1 with an errno of ENOTCONN. On second connect() it
returns -1 with an errno of EALREADY.

On Linux (v 2.4.18):

read() returns 0 with an errno of 115. On Linux 115 corresponds to 
-EINPROGRESS. So as with Digital UNIX, the errno isn't from read but
from our first conect(). On second connect(), it returns -1 with
an errno of -EALREADY.


Is using write() instead of read() a better way? 

To do this, we change our previous program, instead of reading 0
bytes this time we issue a write() of 0 bytes.

On Solaris (SunOS 5.6):

write() returns -1 with an errno of -ENOTCONN.

On Digital UNIX (OSF1 4.0):

write() returns -1 with an errno of -ENOTCONN. We note that previously
a read() returned 0. This behavior is inconsistent. There is a bug in 
Digital UNIX.

On Linux (v 2.4.18):

write() returns 0.


We note that Solaris and Linux are consistent with their read() and write()
for a in-progress socket.

I guess the moral story is don't try to use read() or write() to test 
if a socket is connected or not. :-) It looks to me that issuing a 
second connect() and see if it returns -EISCONN is probably a more
portable way. Of course, following up on the previous discussion, one
must handle a -EALREADY from connect() as well.



> > it should be trivial to hand edit my prevoius patch posted.
> 
> Yes, of course. Though the first part of it also from the class
> "does not matter", it is worth to do this just for sanity.
> 

Yep. Though I would really like it if it conforms to what the rest of 
the Unices does with that behavior.

So, we can agree that the first part should be applied on the next
networking merge? :-)


	-- G.

  reply	other threads:[~2002-08-13  2:21 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-08-10 10:24 [PATCH] connect() return value Geoffrey Lee
2002-08-11 20:46 ` kuznet
2002-08-11 23:25   ` Geoffrey Lee
2002-08-12  1:28     ` kuznet
2002-08-13  2:21       ` Geoffrey Lee [this message]
2002-08-13  4:44         ` kuznet
2002-08-13  5:37           ` Geoffrey Lee
2002-08-13 10:17             ` kuznet
2002-08-13 11:34               ` Geoffrey Lee
2002-08-13 13:47                 ` kuznet
2002-08-13 14:32                   ` Geoffrey Lee
2002-08-13 15:28                     ` kuznet
2002-08-13 23:51                       ` Geoffrey Lee
2002-08-14  0:36                         ` kuznet
2002-08-14  3:02                           ` Geoffrey Lee
2002-08-14  4:16                             ` kuznet
2002-08-14  4:57                               ` Geoffrey Lee
2002-08-14 17:25                                 ` kuznet
2002-08-15  3:25                                   ` glee
2002-08-15  3:15                                     ` David S. Miller
2002-08-15 11:02                                       ` Geoffrey Lee
2002-08-15 21:23                                         ` David S. Miller
2002-08-16  1:08                                           ` Geoffrey Lee

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20020813022115.GA11627@anakin.wychk.org \
    --to=glee@gnupilgrims.org \
    --cc=kuznet@ms2.inr.ac.ru \
    --cc=netdev@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).