in reply to open3 hangs

Maybe try:
$pid = open3(\*CHLDIN, \*CHLDOUT, \*CHLDERR, @$cmd); close(CHLDIN);

By the way, your usage of eval { .. }; if ($@) { .. } can lead to problems. Consider the eval { ..; 1 } or do { .. } idiom from this example:
# timeout handling { local $@ = ""; eval { local $SIG{ALRM} = sub { die("alarm\n") }; # "\n" required alarm(3); # potentially long operation chomp($input = <STDIN>); alarm(0); 1; } or do { die($@) unless $@ eq "alarm\n"; # timed out warn("No answer for three seconds.\n"); $input = ""; } }