Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Gearman CPAN distribution.

Report information
The Basics
Id: 88054
Status: open
Priority: 0/
Queue: Gearman

People
Owner: info [...] maximka.de
Requestors: leonerd-cpan [...] leonerd.org.uk
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.11
Fixed in: (no value)



Subject: [PATCH] Improved Gearman::Client socket timeout behaviour
Gearman::Client has a fixed 1-second connect() timeout, and behaves poorly if this ever expires; failing to notice and instead causing a death by attempting to call ->syswrite on undef. The attached patch propagates the socket connect() failure correctly, and allows for a user-specified timeout. -- Paul Evans
Subject: timeout.patch
=== modified file 'lib/Gearman/Client.pm' --- lib/Gearman/Client.pm 2013-08-12 16:28:10 +0000 +++ lib/Gearman/Client.pm 2013-08-21 15:35:10 +0000 @@ -3,7 +3,7 @@ package Gearman::Client; our $VERSION; -$VERSION = '1.11'; +$VERSION = '1.11_001'; use strict; use IO::Socket::INET; @@ -25,6 +25,7 @@ $self->{hooks} = {}; $self->{prefix} = ''; $self->{exceptions} = 0; + $self->{timeout} = 1; $self->debug($opts{debug}) if $opts{debug}; @@ -36,6 +37,8 @@ $self->prefix($opts{prefix}) if $opts{prefix}; + $self->timeout($opts{timeout}) if $opts{timeout}; + return $self; } @@ -212,7 +215,7 @@ } my $sock = IO::Socket::INET->new(PeerAddr => $hostport, - Timeout => 1) + Timeout => $self->timeout) or return undef; setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; @@ -238,10 +241,16 @@ $self->{sock_cache}{$hostport} ||= $sock; } +# returns a socket connected to a randomly-chosen jobserver, or false +# if they all failed. +# Will leave its error message in $@ from IO::Socket::connect() sub _get_random_js_sock { my Gearman::Client $self = shift; my $getter = shift; - return undef unless $self->{js_count}; + unless( $self->{js_count} ) { + $@ = "No jobservers"; + return (); + } $getter ||= sub { my $hostport = shift; return $self->_get_js_sock($hostport); }; @@ -267,6 +276,12 @@ return $self->{debug} || 0; } +sub timeout { + my Gearman::Client $self = shift; + $self->{timeout} = shift if @_; + return $self->{timeout}; +} + 1; __END__ @@ -324,6 +339,10 @@ Calls I<prefix> (see below) to set the prefix / namespace. +=item * timeout + +Sets the connect timeout, in seconds. + =back =head2 $client->job_servers(@servers) @@ -382,6 +401,10 @@ See L<Gearman::Worker> for more details. +=head2 $client-E<gt>timeout($timeout) + +Sets or returns the connect timeout, in seconds. + =head1 EXAMPLES === modified file 'lib/Gearman/Objects.pm' --- lib/Gearman/Objects.pm 2013-08-12 16:28:10 +0000 +++ lib/Gearman/Objects.pm 2013-08-21 15:37:54 +0000 @@ -14,6 +14,7 @@ 'prefix', 'debug', 'exceptions', + 'timeout', ); package Gearman::Taskset; === modified file 'lib/Gearman/Taskset.pm' --- lib/Gearman/Taskset.pm 2013-08-12 16:28:10 +0000 +++ lib/Gearman/Taskset.pm 2013-08-12 16:41:54 +0000 @@ -227,8 +227,9 @@ }; my ($jst, $jss) = $ts->{client}->_get_random_js_sock($getter); + $jst or die "Unable to connect to jobserver: $@"; + $ts->{loaned_sock}{$jst} ||= $jss; - $ts->{default_sock} = $jss; $ts->{default_sockaddr} = $jst; return $jss;