Skip Menu |

This queue is for tickets about the Catalyst-Devel CPAN distribution.

Report information
The Basics
Id: 119830
Status: resolved
Priority: 0/
Queue: Catalyst-Devel

People
Owner: Nobody in particular
Requestors: arc [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 1.40



Subject: Catalyst::Restarter wastes FDs under kqueue-based File::ChangeNotify watchers
On BSD-like operating systems (including Mac OS), File::ChangeNotify prefers to use IO::KQueue to watch for filesystem changes. The way kqueue works requires holding an open file descriptor for every 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. The attached patch fixes this by having Catalyst::Restarter::Forking clear the watcher in the child process, implicitly closing all the watched descriptors; while the parent process retains the watcher as expected.
Subject: 0001-Catalyst-Restarter-Forking-clear-watcher-in-child-pr.patch
From 16b1e5f59b47c4b11752098d2ca7bca8ff5e3d76 Mon Sep 17 00:00:00 2001 From: Aaron Crane <arc@cpan.org> Date: Thu, 12 Jan 2017 09:45:30 +0000 Subject: [PATCH] Catalyst::Restarter::Forking: clear watcher in child process 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. --- lib/Catalyst/Restarter.pm | 5 +++-- lib/Catalyst/Restarter/Forking.pm | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Catalyst/Restarter.pm b/lib/Catalyst/Restarter.pm index 5ce4ea4..81295f1 100644 --- a/lib/Catalyst/Restarter.pm +++ b/lib/Catalyst/Restarter.pm @@ -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 => ( diff --git a/lib/Catalyst/Restarter/Forking.pm b/lib/Catalyst/Restarter/Forking.pm index 40c81f0..a45e516 100644 --- a/lib/Catalyst/Restarter/Forking.pm +++ b/lib/Catalyst/Restarter/Forking.pm @@ -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->(); } } -- 2.11.0