shugo / ruby-lang.org wrote:
> Eric Wong wrote:
> >  > Ah, I see.  However, if getsockopt() returns no error, we can know
> >  > that at least connect() succeeded, right?  I'm not sure whether it's a
> >  > so-called race condition.
> >  
> >  I'm not sure if we can know for sure due to implementation differences.
> 
> Hmm..., do you know any implementation where getsockopt(SO_ERROR) causes a problem?
> If there's such an implementation, it would be better to remove the call, but I don't come up with such a situation.

I'm not sure about implementations of getsockopt(SO_ERROR),
there are too many differences from what I see.

However, our use of getsockopt(SO_ERROR) causes problems
for maintainability and seems to lead to bugs.

> By contraries, getsockopt(SO_ERROR) might be necessary for winsock, if usa's comment is right.

I'm not sure...
usa: can you try my last patch?
  http://bogomips.org/ruby.git/patch?id=f5e2eb00e5

> >  And even if connect() succeeded, the server could decide to disconnect
> >  right away after accept() due to overload, so probably less important.
> 
> It applies equally to connect() without signal interruption.
> TCPSocket.new should handle EINTR as transparently as possible, I think.

Agreed, and my f5e2eb00e5 patch handles EINTR.

> >  > >  anyways, getsockopt(SO_ERROR) is worthless.
> >  
> >  > I don't think getsockopt(SO_ERROR) is worthless because users can know
> >  > error information sooner and more exactly than subsequent read() or
> >  > write().
> >  
> >  The error may be seen sooner, but I think the errors are uncommon
> >  and most users will not care.  They will see any error and handle it
> >  their own way.
> 
> Most applications might handle errors roughly, but logging the exact error information would help trouble shooting.

Yes, and connect() still shows ETIMEDOUT/ECONNRESET/EHOSTUNREACH/etc.
Interrupted connect() is rare, so I think having the extra
hard-to-maintain code causes more problems than it solves.
I don't think users will care which of connect/write/read fails,
they just need to know an error happened.

> > I have no idea how portable this is:
> > http://bogomips.org/ruby.git/patch?id=f5e2eb00e5
> > 
> > Btw, I suspect the WAIT_IN_PROGRESS stuff is carried over from the
> > 1.8 days where all sockets were non-blocking by default, and overly
> > complicated as a result. I don't even think EINPROGRESS/EAGAIN is
> > possible, only EINTR/ERESTART.
> 
> The patch worked both on Linux 3.2.0 and FreeBSD 10.0 for blocking sockets with signal interruption.

Thanks for testing.  I expect it to have no problem on most *BSD.
I mainly wanted some Win/Solaris/Apple users to try it.

> It might be better to re-call connect() on ERESTART as the error suggests, but I'm not sure.
> It seems to be a Linux way to re-call connect(), but there's no description about ERESTART in Linux's manual of connect(2) and instead there's a reference to POSIX.1-2001 (SUSv3), to which Linux seem not to conform.  Funny.

I'm not sure, either.  ERESTART should be handled by the system C
library and not seen by us, even.  Not sure which (or any currently
supported) systems leak ERESTART...