joyent/node — pull request #2524 by koichik (2012-01-12 06:01:16+00:00)
Title: streams: pipe is destructed by 'end' event from destination

`'end'` event is emitted from a readable stream, not a writable stream (see also [API docs](http://nodejs.org/docs/latest/api/streams.html)). However, `Stream.pipe()` destructs a pipeline by `'end'` event from destination that is a writable stream ([source](https://github.com/joyent/node/blob/b3f91f15b2482a8f3e5d37f0e09429a4b4775230/lib/stream.js#L115)). This behavior causes a problem when duplex stream (i.e. `net.Socket`) with `allowHalfOpen: true` is used.

For example, here is three streams:

```javascript
var reader = ...; // readable stream
var writer = ...; // writable stream
var socket = net.connect({port: 80, allowHalfOpen: true}); // duplex stream
```

Constructs two pipelines:

```javascript
reader.pipe(socket); // pipeline (A)
socket.pipe(writer); // pipeline (B)
```

+--------+ (A) +--------+
| reader | ----> | |
+--------+ | |
| socket |
+--------+ (B) | |
| writer | <---- | |
+--------+ +--------+

When the socket receives a FIN packet, `socket` emits `'end'` event. Then, `Stream.pipe()` destructs not only pipeline (B), but also pipeline (A). Please note that `socket` is still opened and writable.

After that, if `reader` emits `'data'` event, the data is not written to `socket`. And if `reader` emits `'end'` event, `socket.end()` is never called. It makes resource (fd) leaks.

I think that `Stream.pipe()` should not destruct pipeline by `'end'` event from destination.

Please review.