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;