Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Defer rethrowing exceptions until after run() cleans up. Previously

exceptions would be thrown farther inside POE's dispatcher, preventing
some important cleanup.  This only affects a few people who re-run()
POE::Kernel after an exception or using $kernel->stop().
  • Loading branch information...
commit de5ceb83bed758f82b1121301c266633a9f3cccf 1 parent 85268fe
@rcaputo authored
Showing with 27 additions and 21 deletions.
  1. +24 −7 poe/lib/POE/Kernel.pm
  2. +3 −14 poe/lib/POE/Resource/Events.pm
View
31 poe/lib/POE/Kernel.pm
@@ -1266,7 +1266,7 @@ sub _finalize_kernel {
# The main loop is done, no matter which event library ran it.
# sig before loop so that it clears the signal_pipe file handler
- $self->_data_sig_finalize();
+ $self->_data_sig_finalize();
$self->loop_finalize();
$self->_data_extref_finalize();
$self->_data_sid_finalize();
@@ -1284,12 +1284,17 @@ sub run_while {
sub run_one_timeslice {
my $self = shift;
+
unless ($self->_data_ses_count()) {
$self->_finalize_kernel();
$kr_run_warning |= KR_RUN_DONE;
+ $kr_exception and $self->_rethrow_kr_exception();
return;
}
+
$self->loop_do_timeslice();
+ $kr_exception and $self->_rethrow_kr_exception();
+
return 1;
}
@@ -1322,13 +1327,28 @@ sub run {
# Clean up afterwards.
$kr_run_warning |= KR_RUN_DONE;
+
+ $kr_exception and $self->_rethrow_kr_exception();
+}
+
+sub _rethrow_kr_exception {
+ my $self = shift;
+
+ # Save the exception lexically.
+ # Clear it so it doesn't linger if run() is called again.
+ my $exception = $kr_exception;
+ $kr_exception = undef;
+
+ # Rethrow it.
+ die $exception if $exception;
}
# Stops the kernel cold. XXX Experimental!
# No events happen as a result of this, all structures are cleaned up
-# except the kernel's. Even the current session is cleaned up, which
-# may introduce inconsistencies in the current session... as
-# _dispatch_event() attempts to clean up for a defunct session.
+# except the kernel's. Even the current session and POE::Kernel are
+# cleaned up, which may introduce inconsistencies in the current
+# session... as _dispatch_event() attempts to clean up for a defunct
+# session.
sub stop {
# So stop() can be called as a class method.
@@ -1339,9 +1359,6 @@ sub stop {
push @children, $self->_data_ses_get_children($session);
}
- # Remove the kernel itself.
- shift @children;
-
# Walk backwards to avoid inconsistency errors.
foreach my $session (reverse @children) {
$self->_data_ses_free($session);
View
17 poe/lib/POE/Resource/Events.pm
@@ -264,20 +264,9 @@ sub _data_ev_dispatch_due {
$self->_data_ev_refcount_dec($event->[EV_SOURCE], $event->[EV_SESSION]);
$self->_dispatch_event(@$event, $due_time, $id);
- # An exception occurred.
- if ($POE::Kernel::kr_exception) {
-
- # Save the exception lexically, then clear it so it doesn't
- # linger if run() is called again.
- my $exception = $POE::Kernel::kr_exception;
- $POE::Kernel::kr_exception = undef;
-
- # Stop the kernel. Cleans out all sessions.
- POE::Kernel->stop();
-
- # Throw the exception from way out here.
- die $exception;
- }
+ # Stop the system if an unhandled exception occurred.
+ # This wipes out all sessions and associated resources.
+ POE::Kernel->stop() if $POE::Kernel::kr_exception;
}
# Tell the event loop to wait for the next event, if there is one.
Please sign in to comment.
Something went wrong with that request. Please try again.