I noticed that when using Tk with POE. I had about a 12-8k/sec memory leak. I managed to track it down to the $poe_main_window->afterIdle(....) calls in theloop code for Tk. As far as I can tell it's just with that one call. Here is a patch that works around the leak. I realize the 'afterIdle' calls are used for a reason but I find the persistant leak worse. I posted a report to the ptk list. It's beyond my present time vs. ability constraints to track down and fix. Hopefully they fix it soon.

Jason Adams

diff -Naur POE-0.29.orig/lib/POE/Loop/TkActiveState.pm 
POE-0.29/lib/POE/Loop/TkActiveState.pm
--- POE-0.29.orig/lib/POE/Loop/TkActiveState.pm 2003-12-12 04:05:06.000000000 +0000
+++ POE-0.29/lib/POE/Loop/TkActiveState.pm      2004-08-25 18:04:55.000000000 +0000
@@ -114,6 +114,8 @@
 #
 # -><- We should really stop the poller when there are no handles to
 # watch and resume it as needed.
+{
+       my $firstTimeFlag=1;
 
 sub _poll_for_io {
   if (defined $_handle_poller) {
@@ -243,15 +245,21 @@
   # Dispatch whatever events are due.
   $poe_kernel->_data_ev_dispatch_due();
 
-  # Reset the poller.
-  $_handle_poller = $poe_main_window->afterIdle(
-    [ sub {
-        $_handle_poller->cancel();
-        undef $_handle_poller;
-        $_handle_poller = $poe_main_window->after(100, [\&_poll_for_io]);
-      }
-    ]
-  );
+  if($firstTimeFlag) {
+         # Reset the poller.
+         $_handle_poller = $poe_main_window->afterIdle(\&_setPollOnIdle);
+         $firstTimeFlag=0;
+  } else {
+       _setPollOnIdle()
+  }
+}
+
+sub _setPollOnIdle {
+       $_handle_poller->cancel() if($_handle_poller);
+       undef $_handle_poller;
+       $_handle_poller = $poe_main_window->after(100, [\&_poll_for_io]);
+}
+
 }
 
 1;
diff -Naur POE-0.29.orig/lib/POE/Loop/TkCommon.pm POE-0.29/lib/POE/Loop/TkCommon.pm
--- POE-0.29.orig/lib/POE/Loop/TkCommon.pm      2004-01-21 17:27:01.000000000 +0000
+++ POE-0.29/lib/POE/Loop/TkCommon.pm   2004-08-25 18:04:55.000000000 +0000
@@ -76,6 +76,8 @@
 # Tk timer callback to dispatch events.
 
 my $last_time = time();
+{
+       my($firstTimeFlag)=1;
 
 sub _loop_event_callback {
   if (TRACE_STATISTICS) {
@@ -106,25 +108,12 @@
 
     # Replace it with an idle event that will reset the alarm.
 
-    $_watcher_timer = $poe_main_window->afterIdle(
-      [
-        sub {
-          $_watcher_timer->cancel();
-          undef $_watcher_timer;
-
-          my $next_time = $poe_kernel->get_next_event_time();
-          if (defined $next_time) {
-            $next_time -= time();
-            $next_time = 0 if $next_time < 0;
-
-            $_watcher_timer = $poe_main_window->after(
-              $next_time * 1000,
-              [\&_loop_event_callback]
-            );
-          }
-        }
-      ],
-    );
+       if($firstTimeFlag) {
+               $_watcher_timer = $poe_main_window->afterIdle( \&_loop_wait_for_event);
+               $firstTimeFlag=0;
+       } else {
+      _loop_wait_for_event();
+       }
 
     # POE::Kernel's signal polling loop always keeps one event in the
     # queue.  We test for an idle kernel if the queue holds only one
@@ -145,6 +134,23 @@
   # And back to Tk, so we're in idle mode.
   $last_time = time() if TRACE_STATISTICS;
 }
+}
+
+sub _loop_wait_for_event{
+  $_watcher_timer->cancel() if($_watcher_timer);
+  undef $_watcher_timer;
+
+  my $next_time = $poe_kernel->get_next_event_time();
+  if (defined $next_time) {
+    $next_time -= time();
+    $next_time = 0 if $next_time < 0;
+
+    $_watcher_timer = $poe_main_window->after(
+      $next_time * 1000,
+      [\&_loop_event_callback]
+    );
+  }
+}
 
 #------------------------------------------------------------------------------
 # Tk traps errors in an effort to survive them.  However, since POE

Reply via email to