Skip to content

Commit

Permalink
make Mojo::Reactor::Poll a little faster and reliable
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Feb 11, 2015
1 parent 577d17c commit f3a06f3
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 17 deletions.
1 change: 1 addition & 0 deletions Changes
Expand Up @@ -3,6 +3,7 @@
- Replaced expires method in Mojo::Cookie::Response with an attribute.
- Added split_cookie_header function to Mojo::Util.
- Relaxed RFC 822/1123 and RFC 850/1036 handling in Mojo::Date.
- Improved Mojo::Reactor::Poll performance.
- Improved design of built-in templates.
- Fixed bug in Mojo::DOM that made parsing a requirement.
- Fixed warnings in Mojo::URL.
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Reactor.pm
Expand Up @@ -14,7 +14,7 @@ sub detect {

sub io { croak 'Method "io" not implemented by subclass' }

# This may break at some point in the future, but is worth it for performance
# This may break in the future, but is worth it for performance
sub is_readable {
!(IO::Poll::_poll(0, fileno(pop), my $dummy = POLLIN | POLLPRI) == 0);
}
Expand Down
32 changes: 16 additions & 16 deletions lib/Mojo/Reactor/Poll.pm
Expand Up @@ -28,7 +28,6 @@ sub one_tick {

# Wait for one event
my $i;
my $poll = $self->_poll;
until ($i) {

# Stop automatically if there is nothing to watch
Expand All @@ -41,14 +40,21 @@ sub one_tick {

# I/O
if (keys %{$self->{io}}) {
$poll->poll($timeout);
for my $handle ($poll->handles(POLLIN | POLLPRI | POLLHUP | POLLERR)) {
next unless my $io = $self->{io}{fileno $handle};
++$i and $self->_sandbox('Read', $io->{cb}, 0);
}
for my $handle ($poll->handles(POLLOUT)) {
next unless my $io = $self->{io}{fileno $handle};
++$i and $self->_sandbox('Write', $io->{cb}, 1);
my @poll = map { $_ => $self->{io}{$_}{mode} } keys %{$self->{io}};

# This may break in the future, but is worth it for performance
if (IO::Poll::_poll($timeout, @poll) > 0) {
while (@poll) {
my ($fd, $mode) = (shift(@poll), shift(@poll));
if ($mode & (POLLIN | POLLPRI | POLLHUP | POLLERR)) {
next unless my $io = $self->{io}{$fd};
++$i and $self->_sandbox('Read', $io->{cb}, 0);
}
if ($mode & POLLOUT) {
next unless my $io = $self->{io}{$fd};
++$i and $self->_sandbox('Write', $io->{cb}, 1);
}
}
}
}

Expand Down Expand Up @@ -80,7 +86,6 @@ sub recurring { shift->_timer(1, @_) }
sub remove {
my ($self, $remove) = @_;
return !!delete $self->{timers}{$remove} unless ref $remove;
$self->_poll->remove($remove);
return !!delete $self->{io}{fileno $remove};
}

Expand All @@ -102,10 +107,7 @@ sub watch {
my $mode = 0;
$mode |= POLLIN | POLLPRI if $read;
$mode |= POLLOUT if $write;

my $poll = $self->_poll;
$poll->remove($handle);
$poll->mask($handle, $mode) if $mode != 0;
$self->{io}{fileno $handle}{mode} = $mode;

return $self;
}
Expand All @@ -117,8 +119,6 @@ sub _id {
return $id;
}

sub _poll { shift->{poll} ||= IO::Poll->new }

sub _sandbox {
my ($self, $event, $cb) = (shift, shift, shift);
eval { $self->$cb(@_); 1 } or $self->emit(error => "$event failed: $@");
Expand Down

2 comments on commit f3a06f3

@jamadam
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been suffering undef warning on ua request until v5.77, which was once mentioned on ML before.
This commit seems like fix it. Thank you!

https://groups.google.com/forum/#!topic/mojolicious/V3qeMVmMGp8

Use of uninitialized value in hash element at /usr/local/share/perl/5.14.2/Mojo/Reactor/Poll.pm line 46.

For reference, It has been very rare like occuring once among hundreds of Mojo::UserAgent requests
and was because $handle might be closed inside the same 'for' loop and fileno returns undef.
Couldn't figure out how to easily reproduce, though.

@kraih
Copy link
Member Author

@kraih kraih commented on f3a06f3 Feb 12, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😎

Please sign in to comment.