Skip to content

Commit

Permalink
allow Mojo::Server::Daemon to log when a connection has been closed p…
Browse files Browse the repository at this point in the history
…rematurely
  • Loading branch information
kraih committed Apr 21, 2016
1 parent 5685407 commit 5038a1b
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 9 deletions.
2 changes: 2 additions & 0 deletions Changes
@@ -1,6 +1,8 @@

6.59 2016-04-21
- Improved HTML Living Standard compliance of Mojo::DOM::HTML.
- Improved Mojo::Server::Daemon to log when a connection has been closed
prematurely.
- Improved Mojo::Server::Prefork to log when the manager process has been
stopped.
- Fixed a few tests to keep up with breaking changes in IO::Socket::SSL.
Expand Down
6 changes: 5 additions & 1 deletion lib/Mojo/Server/Daemon.pm
Expand Up @@ -118,7 +118,11 @@ sub _close {
my ($self, $id) = @_;

# Finish gracefully
if (my $tx = $self->{connections}{$id}{tx}) { $tx->closed }
if (my $tx = $self->{connections}{$id}{tx}) {
$tx->closed;
$self->_debug($id, 'Premature connection close')
unless $tx->is_websocket || $tx->res->is_finished;
}

delete $self->{connections}{$id};
}
Expand Down
16 changes: 12 additions & 4 deletions lib/Mojolicious/Guides/FAQ.pod
Expand Up @@ -248,10 +248,18 @@ request.

=head2 What does "Premature connection close" mean?

This error message is often related to the one above, and means that the web
server closed the connection before the user agent could receive the whole
response or that the user agent got destroyed, which forces all connections to
be closed immediately.
On the I<client-side> this message is often related to the one above, and means
that the web server closed the connection before the user agent could receive
the whole response, or that the user agent got destroyed, which forces all
connections to be closed immediately.

On the I<server-side> this message means that the user agent closed the
connection before the web server could send the whole response. While this is
generally harmless in itself, special care must be taken for non-blocking
operations that might still be active, because once the connection has been
closed L<Mojolicious::Controller/"tx"> will no longer be available. In such
cases you can use events like L<Mojolicious::Transaction/"finish"> for cleaning
up, or keep an extra reference to the transaction object.

=head2 What does "Worker 31842 has no heartbeat, restarting" mean?

Expand Down
10 changes: 6 additions & 4 deletions t/mojolicious/longpolling_lite_app.t
Expand Up @@ -300,15 +300,17 @@ Mojo::IOLoop->one_tick until $stash->{destroyed};
ok !$stash->{writing}, 'finish event timing is right';
ok $stash->{destroyed}, 'controller has been destroyed';

# Request timeout
$tx = $t->ua->request_timeout(0.5)->get('/too_long');
# Request and inactivity timeouts
$log = '';
$cb = $t->app->log->on(message => sub { $log .= pop });
$tx = $t->ua->request_timeout(0.5)->get('/too_long');
is $tx->error->{message}, 'Request timeout', 'right error';
$t->ua->request_timeout(0);

# Inactivity timeout
$tx = $t->ua->inactivity_timeout(0.5)->get('/too_long');
is $tx->error->{message}, 'Inactivity timeout', 'right error';
$t->ua->inactivity_timeout(20);
like $log, qr/Premature connection close/, 'right message';
$t->app->log->unsubscribe(message => $cb);

# Transaction is available after rendering early in steps
$t->get_ok('/steps')->status_is(200)->content_is('second');
Expand Down

0 comments on commit 5038a1b

Please sign in to comment.