sub run {
my ( $self, $class, $port, $host, $options ) = @_;
- our $GOT_HUP;
- local $GOT_HUP = 0;
-
- local $SIG{HUP} = sub { $GOT_HUP = 1; };
- local $SIG{CHLD} = 'IGNORE';
+ $options ||= {};
# Setup restarter
my $restarter;
my $parent = $$;
unless ( $restarter = fork ) {
+ # Prepare
+ close STDIN;
+ close STDOUT;
+
# Index parent directory
my $dir = File::Spec->catdir( $FindBin::Bin, '..' );
my $regex = $options->{restart_regex};
- my $one = _index( $dir, $regex );
- while (1) {
- sleep $options->{restart_delay};
- my $two = _index( $dir, $regex );
- if ( my $file = _compare_index( $one, $two ) ) {
- print STDERR qq/File "$file" modified, restarting\n/;
- kill( 1, $parent );
+ my $one = _index( $dir, $regex );
+ RESTART: while (1) {
+ sleep $options->{restart_delay} || 1;
+
+ # check if our parent has died
+ exit if ( getppid == 1 );
+
+ my $two = _index( $dir, $regex );
+ my $changes = _compare_index( $one, $two );
+ if (@$changes) {
$one = $two;
+
+ # Test modified pm's
+ for my $file (@$changes) {
+ next unless $file =~ /\.pm$/;
+ if ( my $error = _test($file) ) {
+ print STDERR
+ qq/File "$file" modified, not restarting\n\n/;
+ print STDERR '*' x 80, "\n";
+ print STDERR $error;
+ print STDERR '*' x 80, "\n";
+ next RESTART;
+ }
+ }
+
+ # Restart
+ my $files = join ', ', @$changes;
+ print STDERR qq/File(s) "$files" modified, restarting\n\n/;
+ kill( 1, $parent );
+ exit;
}
}
}
}
+
+ our $GOT_HUP;
+ local $GOT_HUP = 0;
+
+ local $SIG{HUP} = sub { $GOT_HUP = 1; };
+ local $SIG{CHLD} = 'IGNORE';
# Handle requests
# Setup socket
$host = $host ? inet_aton($host) : INADDR_ANY;
- socket( HTTPDaemon, PF_INET, SOCK_STREAM, getprotobyname('tcp') );
- setsockopt( HTTPDaemon, SOL_SOCKET, SO_REUSEADDR, pack( "l", 1 ) );
- bind( HTTPDaemon, sockaddr_in( $port, $host ) );
- listen( HTTPDaemon, SOMAXCONN );
+ socket( HTTPDaemon, PF_INET, SOCK_STREAM, getprotobyname('tcp') )
+ || die "Couldn't assign TCP socket: $!";
+ setsockopt( HTTPDaemon, SOL_SOCKET, SO_REUSEADDR, pack( "l", 1 ) )
+ || die "Couldn't set TCP socket options: $!";
+ bind( HTTPDaemon, sockaddr_in( $port, $host ) )
+ || die "Couldn't bind socket to $port on $host: $!";
+ listen( HTTPDaemon, SOMAXCONN )
+ || die "Couldn't listen to socket on $port on $host: $!";
my $url = 'http://';
if ( $host eq INADDR_ANY ) {
require Sys::Hostname;
if ($GOT_HUP) {
$SIG{CHLD} = 'DEFAULT';
- exec {$0}( ( ( -x $0 ) ? () : ($^X) ), $0, @ARGV );
+ wait;
+ exec {$0}( ( ( -x $0 ) ? () : ($^X) ), $0, @{ $options->{argv} } );
}
}
sub _compare_index {
my ( $one, $two ) = @_;
my %clone = %$two;
+ my @changes;
while ( my ( $key, $val ) = each %$one ) {
- return $key if ( !$clone{$key} || ( $clone{$key} ne $val ) );
+ if ( !$clone{$key} || ( $clone{$key} ne $val ) ) {
+ push @changes, $key;
+ }
delete $clone{$key};
}
- if ( keys %clone ) {
- return join ' ', keys %clone;
- }
- return 0;
+ for my $key ( keys %clone ) { push @changes, $key }
+ return \@changes;
}
sub _get_line {
return \%index;
}
+sub _test {
+ my $file = shift;
+ delete $INC{$file};
+ local $SIG{__WARN__} = sub { };
+ open my $olderr, '>&STDERR';
+ open STDERR, '>', File::Spec->devnull;
+ eval "require '$file'";
+ open STDERR, '>&', $olderr;
+ return $@ if $@;
+ return 0;
+}
+
=back
=head1 SEE ALSO