--- /dev/null
+
+package Spong::SafeExec;
+
+use Carp qw(croak carp);
+use Exporter ();
+
+use vars qw($VERSION @ISA @EXPORT_OK);
+
+$VERSION = 0.01;
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(safe_exec);
+
+sub safe_exec {
+ my($cmd,$timeout) = @_;
+ my (@output);
+
+ $timeout = 15 if $timeout <= 0;
+
+ my $pid = open(CMD, "-|");
+
+ if ($pid) { # I'm the parent
+
+ $message = "";
+ eval {
+ local $SIG{'ALRM'} = sub { die };
+ alarm($timeout);
+
+ @output = <CMD>;
+
+ alarm(0);
+ };
+
+ close CMD or !$! or croak "Error closing CMD fh: $!";
+ alarm(0);
+
+ # Handle child process is not gone
+ if ( kill 0,$pid ) {
+ kill "INTR",$pid; # Try control+C
+ sleep 1; # Give it time to die
+
+ if ( kill 0, $pid ) {
+ kill 9,$pid; # If still alive, nuke it
+ if ( kill 0, $pid ) {
+ carp "Could not kill pid $pid";
+ }
+ }
+
+ }
+
+ } else {
+ exec($cmd) || croak "cannot exec program $cmd: $!";
+ }
+
+ wantarray ? @output : join '', @output;
+}
+
+
+1;