This is harder than it seems. You should do as little as possible in your signal handler because in many versions of Perl you can crash in the signal handler due to non-reentrant system libraries. Beware also of slow system calls which may be automatically restarted after an alarm.
Notice that $x = <COM> will hang if you don't get a newline. So you may need to resort to sysread instead. Anyway, I hope the following example code may be of some use to you.
my $N = 10; # timeout in seconds my $out; # read into here # See Perl Cookbook 2nd edition, Recipe 16.21 # See also perlfaq8 "How do I timeout a slow event". # Read a chunk from file handle <COM>, timing out after $N seconds. # Return number of bytes read, 0 if EOF, -1 if timed out. sub read_for { my $diestr = 0; my $nbytes = 0; eval { local $SIG{ALRM} = sub { die "alarm clock restart" }; alarm($N); # schedule alarm in $N seconds eval { $nbytes = sysread(COM, $out, 1024); }; $diestr = $@ if $@; alarm(0); # cancel the alarm }; $diestr = $@ if $@; alarm(0); # race condition protection return $nbytes unless $diestr; return -1 if $diestr =~ /alarm clock restart/; die $diestr; } while (1) { my $nbytes = read_for(); if ($nbytes < 0) { print "timed out after $N seconds\n"; last; } elsif ($nbytes == 0) { print "eof\n"; last; } print "chunk='$out'\n"; }
In reply to Re: Serial I/O and time question
by eyepopslikeamosquito
in thread Serial I/O and time question
by shepner
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |