Browse files

Fix fd leak when reconnecting in set_receiver.

  • Loading branch information...
1 parent 8cfc3be commit d2b90f3315460a547f2c490445211c76c8a6ff7b @athomason committed Dec 29, 2011
Showing with 91 additions and 4 deletions.
  1. +2 −0 Changes
  2. +8 −0 Fast.xs
  3. +16 −0 LogSyslogFast.c
  4. +2 −0 LogSyslogFast.h
  5. +1 −0 MANIFEST
  6. +1 −1 META.yml
  7. +1 −1 README
  8. +1 −1 lib/Log/Syslog/Fast.pm
  9. +1 −1 lib/Log/Syslog/Fast/XS.pm
  10. +58 −0 t/08-fd-leak.t
View
2 Changes
@@ -1,4 +1,6 @@
Revision history for Perl extension Log::Syslog::Fast.
+0.57 Thu Dec 29 11:49:30 PST 2011
+ - Fix fd leak when reconnecting. Thanks maxs@.
0.56 Sat Nov 5 19:44:36 PDT 2011
- Fix documentation for set_receiver. Thanks maxs@.
0.55 Mon Apr 11 16:41:43 PDT 2011
View
8 Fast.xs
@@ -173,3 +173,11 @@ CODE:
RETVAL = LSF_get_pid(logger);
OUTPUT:
RETVAL
+
+int
+_get_sock(logger)
+ LogSyslogFast* logger
+CODE:
+ RETVAL = LSF_get_sock(logger);
+OUTPUT:
+ RETVAL
View
16 LogSyslogFast.c
@@ -51,6 +51,8 @@ LSF_init(
if (!logger)
return -1;
+ logger->sock = -1;
+
logger->pid = getpid();
logger->linebuf = malloc(logger->bufsize = INITIAL_BUFSIZE);
@@ -155,6 +157,14 @@ LSF_set_receiver(LogSyslogFast* logger, int proto, const char* hostname, int por
struct addrinfo* results = NULL;
#endif
+ if (logger->sock >= 0) {
+ int ret = close(logger->sock);
+ if (ret) {
+ logger->err = strerror(errno);
+ return -1;
+ }
+ }
+
/* set up a socket, letting kernel assign local port */
if (proto == LOG_UDP || proto == LOG_TCP) {
@@ -366,3 +376,9 @@ LSF_get_pid(LogSyslogFast* logger)
{
return logger->pid;
}
+
+int
+LSF_get_sock(LogSyslogFast* logger)
+{
+ return logger->sock;
+}
View
2 LogSyslogFast.h
@@ -46,6 +46,8 @@ const char* LSF_get_sender(LogSyslogFast* logger);
const char* LSF_get_name(LogSyslogFast* logger);
int LSF_get_pid(LogSyslogFast* logger);
+int LSF_get_sock(LogSyslogFast* logger);
+
int LSF_send(LogSyslogFast* logger, const char* msg, int len, time_t t);
#endif
View
1 MANIFEST
@@ -13,6 +13,7 @@ t/04-accessors.t
t/05-ipv6.t
t/06-large-strings.t
t/07-Log-Syslog-Fast-PP.t
+t/08-fd-leak.t
t/lib/LSFServer.pm
lib/Log/Syslog/Fast.pm
lib/Log/Syslog/Fast/PP.pm
View
2 META.yml
@@ -1,7 +1,7 @@
# http://module-build.sourceforge.net/META-spec.html
#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
name: Log-Syslog-Fast
-version: 0.56
+version: 0.57
version_from: lib/Log/Syslog/Fast.pm
installdirs: site
requires:
View
2 README
@@ -1,4 +1,4 @@
-Log-Syslog-Fast version 0.56
+Log-Syslog-Fast version 0.57
============================
This module sends syslog messages over a network socket. It works like
View
2 lib/Log/Syslog/Fast.pm
@@ -8,7 +8,7 @@ require Exporter;
use Log::Syslog::Constants ();
use Carp 'croak';
-our $VERSION = '0.56';
+our $VERSION = '0.57';
our @ISA = qw(Log::Syslog::Constants Exporter);
View
2 lib/Log/Syslog/Fast/XS.pm
@@ -8,7 +8,7 @@ require Exporter;
use Log::Syslog::Constants ();
use Carp 'croak';
-our $VERSION = '0.56';
+our $VERSION = '0.57';
require XSLoader;
XSLoader::load('Log::Syslog::Fast::XS', $VERSION);
View
58 t/08-fd-leak.t
@@ -0,0 +1,58 @@
+# test for fix of https://rt.cpan.org/Ticket/Display.html?id=73569
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+use File::Temp 'tempdir';
+use IO::Select;
+use IO::Socket::INET;
+use IO::Socket::UNIX;
+use Log::Syslog::Constants ':all';
+use POSIX 'strftime';
+
+require 't/lib/LSFServer.pm';
+
+use Log::Syslog::Fast ':protos';
+
+my $test_dir = tempdir(CLEANUP => 1);
+
+# old IO::Socket::INET fails with "Bad service '0'" when attempting to use
+# wildcard port
+my $port = 24767;
+sub listen_port {
+ return 0 if $IO::Socket::INET::VERSION >= 1.31;
+ diag("Using port $port for IO::Socket::INET v$IO::Socket::INET::VERSION");
+ return $port++;
+}
+
+my $listener = IO::Socket::INET->new(
+ Proto => 'tcp',
+ Type => SOCK_STREAM,
+ LocalHost => 'localhost',
+ LocalPort => listen_port(),
+ Listen => 5,
+ Reuse => 1,
+) or die $!;
+
+my $server = StreamServer->new(
+ listener => $listener,
+ proto => LOG_TCP,
+ address => [$listener->sockhost, $listener->sockport],
+);
+
+ok($server->{listener}, "listen") or diag("listen failed: $!");
+
+my $logger = $server->connect('Log::Syslog::Fast' => LOG_AUTH, LOG_INFO, 'localhost', 'test');
+
+my $initial_sock = $logger->_get_sock;
+
+for (1 .. 100) {
+ $logger->set_receiver($server->proto, $server->address);
+ $server->accept();
+}
+
+is($logger->_get_sock, $initial_sock, "sock fd is recycled across reconnections")
+ or diag sprintf "sock went from %d to %d\n", $initial_sock, $logger->_get_sock;
+
+# vim: filetype=perl

0 comments on commit d2b90f3

Please sign in to comment.