Catalyst::Restarter::Forking: clear watcher in child process
Aaron Crane [Thu, 12 Jan 2017 09:45:30 +0000 (09:45 +0000)]
This allows any resources held by the watcher to be released in the child
process, where they won't be needed.

This is particularly important in kqueue-based watcher implementations.
The way kqueue works requires an open file descriptor for each file and
directory watched. In the case of modules being loaded from a local::lib,
this can easily amount to many thousands of file descriptors. This is not
only wasteful, but it also prevents select(2) from being called on any
file descriptor subsequently opened: you're likely to get EINVAL because the
descriptor exceeds FD_SETSIZE.

Changes
lib/Catalyst/Restarter.pm
lib/Catalyst/Restarter/Forking.pm

diff --git a/Changes b/Changes
index bb353dd..92f9a61 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,8 @@
 This file documents the revision history for Perl extension Catalyst-Devel.
 
         - Typo fixes. RT#87103
+        - Catalyst::Restarter::Forking: clear watcher in child process.
+          RT#119830
 
 1.39 2013-06-14 12:44:17
         - Write =encoding utf8 into generated Pod files so that things
index 5ce4ea4..81295f1 100644 (file)
@@ -22,8 +22,9 @@ has argv =>  (
 );
 
 has _watcher => (
-    is  => 'rw',
-    isa => 'File::ChangeNotify::Watcher',
+    is      => 'rw',
+    isa     => 'File::ChangeNotify::Watcher',
+    clearer => '_clear_watcher',
 );
 
 has _filter => (
index 40c81f0..a45e516 100644 (file)
@@ -17,6 +17,9 @@ sub _fork_and_start {
         $self->_child($pid);
     }
     else {
+        # Only the parent process needs to watch for changes, so the child
+        # should release any resources held by the watcher:
+        $self->_clear_watcher;
         $self->start_sub->();
     }
 }