Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Fix #83 #84

merged 1 commit into from

2 participants

ap commented

It appears like the correct way to handle EPIPE in this case is simply to stop writing and otherwise ignore it.


How can you reproduce and verify the fix? (and if that can be scripted, can that be turned into a .t?)

ap commented

Depends on what you are trying to test?

If all you want to verify is that sub _syswrite bails out with no error after EPIPE, then it would suffice to use the t/lf_only_request.t approach to add an overridden sysread which returns EPIPE and check that that works with no complaints. I can do that easily.

But if you want to test that the client closing the connection leads to sub _syswrite bailing out with no error, I’m not even sure how to write such a test, since it would need direct control of the client socket. Does Test::TCP provide that? Briefly skimming the docs was inconclusive.


Let me paraphrase: how did you test this commit?

ap commented

Manually, using warn debugging. Without the patch I would randomly get the error from #83 every so often; with this patch, I didn’t. There was no other sign of breakage – the app serves all content correctly, with or without the patch. I then added a warn for every time the error was being ignored and it still triggered like before, but without dying. This is all as it should be, if I understood EPIPE correctly, as meaning simply that the program should stop writing and go home because no one is listening at the other end of a handle.

What I do not understand is why the connections get closed in the first place – but I cannot reproduce the behaviour without a browser and the browser seems to be doing its job just fine anyway, so I guess the EPIPEs being returned are correct and just have to be handled correctly.

(Before the recent SSL patches, the syswrite call return value was never checked, but on non-SSL sockets the data is always sent in a single syswrite call anyway, so never checking the return value worked – but presumably EPIPE was being set already and it never caused a problem. But if this concerns you, I could test this hypothesis by patching a pre-0.4 Starman to check the syswrite return and see if the EPIPEs pop up there.)


I ran the starman server and used ab to send requests, and verified it eliminated that Broken pipe warnings.

@miyagawa miyagawa merged commit 3b9e9d7 into miyagawa:master

1 check passed

Details default The Travis CI build passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 2, 2013
  1. @ap

    stop writing after EPIPE

    ap authored
This page is out of date. Refresh to see the latest.
Showing with 8 additions and 6 deletions.
  1. +8 −6 lib/Starman/
14 lib/Starman/
@@ -8,7 +8,7 @@ use IO::Socket qw(:crlf);
use HTTP::Parser::XS qw(parse_http_request);
use HTTP::Status qw(status_message);
use HTTP::Date qw(time2str);
-use POSIX qw(EINTR);
use Symbol;
use Plack::Util;
@@ -543,13 +543,15 @@ sub _syswrite {
while (length $$buffer_ref) {
my $len = syswrite($conn, $$buffer_ref);
- if (defined $len) {
- substr($$buffer_ref, 0, $len, '');
- DEBUG && warn "[$$] Wrote $len byte", ($len == 1 ? '' : 's'), "\n";
- }
- elsif ($! != EINTR) {
+ if (not defined $len) {
+ return if $! == EPIPE;
+ redo if $! == EINTR;
die "write error: $!";
+ substr($$buffer_ref, 0, $len, '');
+ DEBUG && warn "[$$] Wrote $len byte", ($len == 1 ? '' : 's'), "\n";
Something went wrong with that request. Please try again.