Skip Menu |

This queue is for tickets about the Net-DBus CPAN distribution.

Report information
The Basics
Id: 71943
Status: resolved
Priority: 0/
Queue: Net-DBus

People
Owner: Nobody in particular
Requestors: frank [...] szczerba.net
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in:
  • 0.32.1
  • 0.32.2
  • 0.32.3
  • 0.32.3a
  • 0.33.1
  • 0.33.2
  • 0.33.3
  • 0.33.4
  • 0.33.5
  • 0.33.6
  • 1.0.0
Fixed in: (no value)



Subject: Memory leak with Async messages
Net::DBus leaks when async calls are used. Devel::Leak::Object shows leaks of the following objects: Net::DBus::ASyncReply Net::DBus::Binding::PendingCall application internal DeferredReply object application internal Request object This appears to be due to two reasons: 1. Net::DBus::ASyncReply holds a reference to an instance of Net::DBus::Binding::PendingCall. When Net::DBus::ASyncReply::set_notify is called, it does $self->{pending_call}->set_notify(sub { my $pending_call = shift; &$cb($self); }); this creates a reference from Net::DBus::Binding::PendingCall back to the Net::DBus::ASyncReply instance via the anonymous closure. The get_result and discard_result methods in Net::DBus::ASyncReply are documented as "final" methods, the POD says "After calling this method, this object should not be used again" for both. Therefore, we can break the circular reference by deleting the $self->{pending_call} reference in these methods. This fix addresses the Net::DBus::Binding::PendingCall leak, but not the Net::DBus::ASyncReply leak. 2. The code reference passed to Net::DBus::Binding::PendingCall::set_notify is passed to Net::DBus::Binding::C::PendingCall::_set_notify, which adds a reference to the code object and passes it to the DBus library via dbus_pending_call_set_notify. The helper methods _pending_call_callback and _pending_call_notify_release are registered to process the callback and to free the user data, respectively. The _pending_call_notify_release method removes the reference to the code object added by _set_notify, but was never called (an added debug message in this function did not appear in the log, even though the Net::DBus::Binding::C::PendingCall::DESTROY debug message did appear), implying a reference count issue with the C DBusPendingCall object. The implementation of _pending_call_callback has a dbus_pending_call_ref(call) statement that appears to be out of place, as this is a use of an existing reference, not a new reference. Removing this statement results in _pending_call_notify_release being called and addresses the Net::DBus::ASyncReply leak, along with the app-specific DeferredReply and Request object leaks (which were via the closure passed to Net::DBus::ASyncReply::set_notify). Originally observed this in the CentOS 5.4 shipped Net::DBus lib (0.32?), debugged in 0.33.6. Same code is present in 1.0.0. Tested on perl v5.8.8. I have been running with the attached patch for months under heavy workloads without issue.
Subject: perl-Net-DBus-leak.patch
diff -rup Net-DBus-0.33.6/DBus.xs Net-DBus-0.33.6-leakfix/DBus.xs --- Net-DBus-0.33.6/DBus.xs 2008-02-20 19:26:44.000000000 -0500 +++ Net-DBus-0.33.6-leakfix/DBus.xs 2010-12-01 13:44:56.000000000 -0500 @@ -343,7 +343,8 @@ _pending_call_callback(DBusPendingCall * selfref = (SV*)dbus_pending_call_get_data(call, pending_call_data_slot); self = (HV*)SvRV(selfref); - dbus_pending_call_ref(call); + // Why was this here? It makes the call object leak. - FCS + //dbus_pending_call_ref(call); ENTER; SAVETMPS; @@ -365,6 +366,7 @@ _filter_release(void *data) { void _pending_call_notify_release(void *data) { + DEBUG_MSG("In pending call notify release %p\n", data); SvREFCNT_dec(data); } @@ -1189,7 +1191,7 @@ void DESTROY (call) DBusPendingCall *call; CODE: - DEBUG_MSG("Unrefing pending call %p", call); + DEBUG_MSG("Unrefing pending call %p\n", call); dbus_pending_call_unref(call); MODULE = Net::DBus::Binding::C::Watch PACKAGE = Net::DBus::Binding::C::Watch diff -rup Net-DBus-0.33.6/lib/Net/DBus/ASyncReply.pm Net-DBus-0.33.6-leakfix/lib/Net/DBus/ASyncReply.pm --- Net-DBus-0.33.6/lib/Net/DBus/ASyncReply.pm 2008-02-20 19:26:44.000000000 -0500 +++ Net-DBus-0.33.6-leakfix/lib/Net/DBus/ASyncReply.pm 2010-12-01 12:39:42.000000000 -0500 @@ -84,8 +84,9 @@ calling this method, this object should sub discard_result { my $self = shift; + my $pending_call = delete $self->{pending_call}; - $self->{pending_call}->cancel; + $pending_call->cancel; } @@ -151,8 +152,9 @@ object should no longer be used. sub get_result { my $self = shift; + my $pending_call = delete $self->{pending_call}; - my $reply = $self->{pending_call}->get_reply; + my $reply = $pending_call->get_reply; if ($reply->isa("Net::DBus::Binding::Message::Error")) { my $iter = $reply->iterator();
Thanks for your patch, it looks good to me, so I have applied it to the upstream repository. https://gitorious.org/net-dbus/net-dbus/commit/51c4f20794b925e30ec14b4519c566c3779a9c78 It will be included in the next release