From e6609c39908d37c1e226d2548d0649c751695062 Mon Sep 17 00:00:00 2001
From: Steve Hancock <perltidy@users.sourceforge.net>
Date: Sun, 4 Aug 2024 07:12:25 -0700
Subject: [PATCH] add --timeout-in-seconds=n, -to=n, default n=10 seconds

---
 bin/perltidy     |  9 +++++++++
 lib/Perl/Tidy.pm | 24 +++++++++++++++++++++---
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/bin/perltidy b/bin/perltidy
index 233cbce4..fea1288e 100755
--- a/bin/perltidy
+++ b/bin/perltidy
@@ -416,6 +416,15 @@ other words that the input code is 'untidy' according to the formatting
 parameters.  If this is not the case, an error message noting this is produced.
 This flag has no other effect on the functioning of perltidy.
 
+=item B<-to=n>,   B<--timeout-in-seconds=n>
+
+When the standard input supplies the input stream, and the input has not been
+received within B<n> seconds, perltidy will end with a timeout message.  The
+intention is to catch a situation where perltidy is accidentally invoked
+without a file to process and therefore waits for input from the system
+standard input (stdin), which never arrives.  The default is B<n=10> seconds.
+This check can be turned off with B<n=0>.
+
 =back
 
 =head1 FORMATTING OPTIONS
diff --git a/lib/Perl/Tidy.pm b/lib/Perl/Tidy.pm
index 31f9363a..e33e0977 100644
--- a/lib/Perl/Tidy.pm
+++ b/lib/Perl/Tidy.pm
@@ -306,7 +306,7 @@ EOM
 
 sub stream_slurp {
 
-    my ($filename) = @_;
+    my ( $filename, $timeout_in_seconds ) = @_;
 
     # Read the text in $filename and
     # return:
@@ -358,7 +358,22 @@ EOM
     else {
         if ( $filename eq '-' ) {
             local $INPUT_RECORD_SEPARATOR = undef;
-            my $buf = <>;
+            my $buf;
+            if ( $timeout_in_seconds && $timeout_in_seconds > 0 ) {
+                eval {
+                    local $SIG{ALRM} = sub { die "alarm\n" };
+                    alarm($timeout_in_seconds);
+                    $buf = <>;
+                    alarm(0);
+                    1;
+                }
+                  or Die(
+"Timeout reading stdin using -to=$timeout_in_seconds seconds. Use -to=0 to skip timeout check.\n"
+                  );
+            }
+            else {
+                $buf = <>;
+            }
             $rinput_string = \$buf;
         }
         else {
@@ -1628,7 +1643,8 @@ sub get_decoded_string_buffer {
 
     my $rOpts = $self->[_rOpts_];
 
-    my $rinput_string = stream_slurp($input_file);
+    my $rinput_string =
+      stream_slurp( $input_file, $rOpts->{'timeout-in-seconds'} );
     return unless ( defined($rinput_string) );
 
     # Note that we could have a zero size input string here if it
@@ -3456,6 +3472,7 @@ sub generate_options {
     $add_option->( 'warning-output',             'w',     '!' );
     $add_option->( 'add-terminal-newline',       'atnl',  '!' );
     $add_option->( 'line-range-tidy',            'lrt',   '=s' );
+    $add_option->( 'timeout-in-seconds',         'to',    '=i' );
 
     # options which are both toggle switches and values moved here
     # to hide from tidyview (which does not show category 0 flags):
@@ -3934,6 +3951,7 @@ sub generate_options {
       code-skipping
       format-skipping
       default-tabsize=8
+      timeout-in-seconds=10
 
       whitespace-cycle=0
       entab-leading-whitespace=0
-- 
2.39.5