Subject: | Suggested change in POE/Resource/FileHandles.pm |
Date: | Thu, 12 Jul 2007 10:59:21 -0700 |
To: | rcaputo [...] cpan.org |
From: | Yuri Shtil <yshtil [...] cisco.com> |
Hi Rocco,
I attached a suggested change to the file.
The reason is that the existing code keeps track of the file handles
in hash keyed by the globs . The resultant key is a stringified
reference like GLOB(0x91615e4).
In my case I used POE::Component::Server::TCP to hook HTTP::Daemon on
a connection. I blessed the socket from the client wheel to
HTTP::Daemon which is a subclass of Socket so everything worked fine.
However when the connection and the session was gone, the socket was
stuck because the object reference changed.
My change consists of using the object address as the key since it
will not change when the object is re-blessed.
Please let me know if my solution is acceptable.
--
Yuri Shtil
--- POE/Resource/FileHandles.pm Thu Jul 12 10:40:13 2007
+++ POE_PATCHED/Resource/FileHandles.pm Thu Jul 12 10:37:57 2007
@@ -272,8 +272,17 @@ sub _data_handle_is_good {
### Add a select to the session, and possibly begin a watcher.
+sub _deglob {
+ my ($h) = @_;
+
+ $h =~ m!GLOB\(([^)]+)!;
+ $1;
+}
+
sub _data_handle_add {
my ($self, $handle, $mode, $session, $event) = @_;
+ my $handleref = _deglob($handle);
+
my $fd = fileno($handle);
# First time watching the file descriptor. Do some heavy setup.
@@ -366,7 +375,7 @@ sub _data_handle_add {
# The session is also watching it by the same handle. Treat this
# as a "resume" in this mode.
- if (exists $kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handle}) {
+ if (exists $kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handleref}) {
if (TRACE_FILES) {
_warn(
"<fh> running fileno($fd) mode($mode) " .
@@ -415,7 +424,7 @@ sub _data_handle_add {
# the session/handle pair.
else {
- $kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handle} =
+ $kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handleref} =
[ $handle, # HSS_HANDLE
$session, # HSS_SESSION
$event, # HSS_STATE
@@ -438,8 +447,8 @@ sub _data_handle_add {
# If the session hasn't already been watching the filehandle, then
# register the filehandle in the session's structure.
- unless (exists $kr_ses_to_handle{$session}->{$handle}) {
- $kr_ses_to_handle{$session}->{$handle} =
+ unless (exists $kr_ses_to_handle{$session}->{$handleref}) {
+ $kr_ses_to_handle{$session}->{$handleref} =
[ $handle, # SH_HANDLE
0, # SH_REFCOUNT
[ 0, # SH_MODECOUNT / MODE_RD
@@ -453,7 +462,7 @@ sub _data_handle_add {
# Modify the session's handle structure's reference counts, so the
# session knows it has a reason to live.
- my $ss_handle = $kr_ses_to_handle{$session}->{$handle};
+ my $ss_handle = $kr_ses_to_handle{$session}->{$handleref};
unless ($ss_handle->[SH_MODECOUNT]->[$mode]) {
$ss_handle->[SH_MODECOUNT]->[$mode]++;
$ss_handle->[SH_REFCOUNT]++;
@@ -465,6 +474,8 @@ sub _data_handle_add {
sub _data_handle_remove {
my ($self, $handle, $mode, $session) = @_;
+ my $handleref = _deglob($handle);
+
my $fd = fileno($handle);
# Make sure the handle is deregistered with the kernel.
@@ -477,7 +488,7 @@ sub _data_handle_remove {
if (
exists($kr_fno_rec->[FMO_SESSIONS]->{$session}) and
- exists($kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handle})
+ exists($kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handleref})
) {
TRACE_FILES and
@@ -486,7 +497,7 @@ sub _data_handle_remove {
# Remove the handle from the kernel's session record.
my $handle_rec =
- delete $kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handle};
+ delete $kr_fno_rec->[FMO_SESSIONS]->{$session}->{$handleref};
my $kill_session = $handle_rec->[HSS_SESSION];
my $kill_event = $handle_rec->[HSS_STATE];
@@ -584,12 +595,12 @@ sub _data_handle_remove {
if (
exists($kr_ses_to_handle{$session}) and
- exists($kr_ses_to_handle{$session}->{$handle})
+ exists($kr_ses_to_handle{$session}->{$handleref})
) {
# Remove it from the session's read, write or expedite mode.
- my $ss_handle = $kr_ses_to_handle{$session}->{$handle};
+ my $ss_handle = $kr_ses_to_handle{$session}->{$handleref};
if ($ss_handle->[SH_MODECOUNT]->[$mode]) {
# Hmm... what is this? Was POE going to support multiple
selects?
@@ -606,7 +617,7 @@ sub _data_handle_remove {
}
unless ($ss_handle->[SH_REFCOUNT]) {
- delete $kr_ses_to_handle{$session}->{$handle};
+ delete $kr_ses_to_handle{$session}->{$handleref};
$self->_data_ses_refcount_dec($session);
delete $kr_ses_to_handle{$session}
unless keys %{$kr_ses_to_handle{$session}};