# Socket issue

**URL:** <https://www.ruby-forum.com/t/socket-issue/82949>\
**Category:** Ruby\
**Created:** [January 22, 2007, 4:54pm UTC](https://www.ruby-forum.com/t/socket-issue/82949 "2007-01-22T16:54:40Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mschipperheyn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4491bb/32.png) [@mschipperheyn](https://www.ruby-forum.com/u/mschipperheyn)\
**Post date:** [January 22, 2007, 4:54pm UTC](https://www.ruby-forum.com/t/socket-issue/82949/1 "2007-01-22T16:54:40Z")

</div>

Hey all,

While testing some edge cases in an app I came across a strange socket  
issue. If I have a server that dies unexpectedly, and then try to  
write to it from an already connected client, it doesn’t raise an  
exception until the next time I try to write it.

Example:

## Server

require ‘socket’

include Socket::Constants

sock = Socket.new(AF\_INET, SOCK\_STREAM, 0)  
sock.setsockopt(SOL\_SOCKET, SO\_REUSEADDR, true)  
sockaddr = Socket.pack\_sockaddr\_in(7000, ‘localhost’)  
sock.bind(sockaddr)  
sock.listen(0)

client, client\_sockaddr = sock.accept  
print “Connected\n”  
print “\>\>\> #{client.readline}”  
abort

## Client

require ‘socket’  
include Socket::Constants

$sock = Socket.new(AF\_INET, SOCK\_STREAM, 0)  
sockaddr = Socket.pack\_sockaddr\_in(7000, ‘localhost’)  
$sock.connect(sockaddr)

def send\_msg  
begin  
$sock.write(“Hello\n”)  
rescue StandardError =\> err  
p err  
end  
end

puts “1”  
send\_msg  
sleep 0.5  
puts “2”  
send\_msg # Should error here.  
sleep 0.5  
puts “3”  
send\_msg

Any suggestions? I’m running on Linux, BTW.

Thanks,  
Marc

---

<div class="post-metadata">

**Author:** ![mschipperheyn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4491bb/32.png) [@mschipperheyn](https://www.ruby-forum.com/u/mschipperheyn)\
**Post date:** [January 22, 2007, 5:56pm UTC](https://www.ruby-forum.com/t/socket-issue/82949/2 "2007-01-22T17:56:53Z")

</div>

On Jan 22, 2007, at 10:53 AM, Marc S. wrote:

> Any suggestions? I’m running on Linux, BTW.

What you are seeing is in the nature of TCP.

After the connection succeeds your server shuts down _its_ end of  
the TCP session (i.e. it tells the client that it won’t send any  
more data). Since TCP is full duplex, the client-\> server part of  
the connection is still up and running as far as the client is  
concerned.

Your first write stuffs the data in a buffer and returns (with no  
error). Shortly thereafter the kernel decides to actually transmit  
the data. The server responds with a RESET indicating that it will  
no longer accept data on that TCP session. The error is noted by  
the kernel and is reported to your client code on the _next_ attempt  
to write to the socket (which is now in an error state).

There is no one-to-one mapping of a write call on the socket to  
data transmission on the wire for TCP due to buffering. This is  
why the first write doesn’t cause the transmit/detect/report of  
the error.

Gary W.

---

<div class="post-metadata">

**Author:** ![mschipperheyn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4491bb/32.png) [@mschipperheyn](https://www.ruby-forum.com/u/mschipperheyn)\
**Post date:** [January 23, 2007, 4:59am UTC](https://www.ruby-forum.com/t/socket-issue/82949/3 "2007-01-23T04:59:46Z")

</div>

On 1/22/07, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> the data. The server responds with a RESET indicating that it will

Gary,

First, thanks for your answer. I agree with you, however, my  
understanding was that after the client side kernel flushes it’s  
buffers from the second send(2) (the first send after the server dies)  
the server would send a RST back. If I were to go about other  
processing and not even touch the socket again I should still receive  
and SIGPIPE. Is this not true?

Thanks for your time.  
Marc

---

<div class="post-metadata">

**Author:** ![mschipperheyn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4491bb/32.png) [@mschipperheyn](https://www.ruby-forum.com/u/mschipperheyn)\
**Post date:** [January 23, 2007, 5:29am UTC](https://www.ruby-forum.com/t/socket-issue/82949/4 "2007-01-23T05:29:48Z")

</div>

On Jan 22, 2007, at 10:59 PM, Marc S. wrote:

> First, thanks for your answer. I agree with you, however, my  
> understanding was that after the client side kernel flushes it’s  
> buffers from the second send(2) (the first send after the server dies)  
> the server would send a RST back. If I were to go about other  
> processing and not even touch the socket again I should still receive  
> and SIGPIPE. Is this not true?

The SIGPIPE is sent when you attempt to write to the socket, not when  
the kernel receives the RST. So in your example, the timeline looks  
like:

## client server

```
                     listen

```

connect  
accept  
abort  
\<-----------FIN  
write  
sleep  
| ‘hello’ --------\>  
| \<----------- RST  
write: SIGPIPE

That is a pretty lame diagram but I hope it clarifies things.

FYI, this is a behavior of the underlying socket abstraction, not  
something particular to Ruby.

Gary W.
