From: shugo@... Date: 2014-02-19T12:00:44+00:00 Subject: [ruby-core:60869] [ruby-trunk - Bug #9356] TCPSocket.new does not seem to handle INTR Issue #9356 has been updated by Shugo Maeda. 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. By contraries, getsockopt(SO_ERROR) might be necessary for winsock, if usa's comment is right. > 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. > > > 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. > Ah, I forget the outer for(;;) loop. Maybe it's better to not loop, > the WAIT_IN_PROGRESS stuff is confusing... I agree that the code is complicated, and it's better to simplify it, if possible. > 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. 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. ---------------------------------------- Bug #9356: TCPSocket.new does not seem to handle INTR https://bugs.ruby-lang.org/issues/9356#change-45280 * 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 `
' This also appears to affect 2.0.0. 1.9.3 is unaffected. ---Files-------------------------------- socket-eintr.rb (207 Bytes) -- http://bugs.ruby-lang.org/