Issue #9356 has been updated by Eric Wong.


 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...

----------------------------------------
Bug #9356: TCPSocket.new does not seem to handle INTR
https://bugs.ruby-lang.org/issues/9356#change-45286

* Author: Charlie Somerville
* Status: Open
* Priority: Normal
* Assignee: 
* Category: 
* Target version: 
* ruby -v: -
* Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN, 2.1: UNKNOWN
----------------------------------------
TCPSocket.new does not seem to handle EINTR properly.

In the attached test script, I try to open a TCP connection to my server and make an HTTP request while a background thread continually sends a signal to the process.

This causes the #write call to fail with:

x.rb:13:in `write': Socket is not connected (Errno::ENOTCONN)
	from x.rb:13:in `<main>'

This also appears to affect 2.0.0. 1.9.3 is unaffected.

---Files--------------------------------
socket-eintr.rb (207 Bytes)


-- 
http://bugs.ruby-lang.org/