Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ Advanced options:
code or signal+128. This also makes timeout to wait until the controlled
process is terminated. Without this option, the script returns zero.

* `--memlimit-rss`, `-s` - monitor RSS (resident set size) memory limit
* `--memlimit-rss`, `-s` - monitor RSS (resident set size) memory limit.
Memory limits may be specified as KB (default), MB, or GB.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you documented that the default is Kilobytes. These days, however, it's not clear if that means 1000 bytes or 1024 bytes; can you please clarify?

E.g. 900KB, 100MB, 1.2GB

More options may be read in the script itself. More documentation will be
added in the future releases!
Expand All @@ -108,26 +110,30 @@ EXAMPLES
Since you already have Perl to run the script itself, the examples will
utilize it.

Basic time limiting:
Basic CPU time limiting:

./timeout -t 2 perl -e 'while ($i<100000000) {$i++;}'
Outputs:
TIMEOUT 2.04 CPU

Basic memory limiting (100M of virtual memory):
Basic memory limiting (100MB of virtual memory):

./timeout -m 1000000 perl -e 'while ($i<100000000) {$a->{$i} = $i++;}'
./timeout -m 100MB perl -e 'while ($i<100000000) {$a->{$i} = $i++;}'
Outputs:
MEM 8.55
MEM CPU 0.41 MEM 119236 KB 116 MB 0 GB MAXMEM 119236 KB 116 MB 0 GB STALE 0 MAXMEM_RSS 100432 KB 98 MB 0 GB
<time name="ALL">440</time>

Limit both time and memory (adjust number to match the command above):
Limit both CPU time and memory (adjust number to match the command above). Note that the decision to kill the process is based on the logical OR of the limits:

./timeout -m 1000000 -t 9 perl -e 'while ($i<100000000) {$x->{$i} = $i++;}'
./timeout -m 100mb -t 2 perl -e 'while ($i<100000000) {$i++;}'
Outputs:
MEM 8.57
./timeout -m 1000000 -t 8 perl -e 'while ($i<100000000) {$x->{$i} = $i++;}'
TIMEOUT CPU 2.05 MEM 20552 KB 20 MB 0 GB MAXMEM 20552 KB 20 MB 0 GB STALE 0 MAXMEM_RSS 1748 KB 1 MB 0 GB
<time name="ALL">2100</time>

./timeout -m 100mb -t 9 perl -e 'while ($i<100000000) {$x->{$i} = $i++;}'
Outputs:
TIMEOUT 8.02 CPU
MEM CPU 0.41 MEM 124252 KB 121 MB 0 GB MAXMEM 124252 KB 121 MB 0 GB STALE 0 MAXMEM_RSS 108616 KB 106 MB 0 GB
<time name="ALL">440</time>

Limit time with a lot of short child processes:

Expand Down Expand Up @@ -208,6 +214,3 @@ The script was initially developed in the Institute for System Programming of
Russian Academy of Sciences (http://ispras.ru/en/) for Linux Driver
Verification project (http://forge.ispras.ru/projects/ldv) in 2010-2011 by
Pavel Shved with some contributions from Alexander Strakh.



36 changes: 32 additions & 4 deletions timeout
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@

sub usage{ print STDERR <<usage_ends;
Usage:
timeout [-t timelimit] [-m memlimit] [-x hertz] command [arguments ...]
timeout [-t timelimit] [-m memlimit] [-s memlimit-rss] [-x hertz] command [arguments ...]

Memory limits may be specified as KB (default), MB, or GB.
Example: timeout -memlimit 2.5GB -memlimit-rss 7800MB

usage_ends
die;
Expand Down Expand Up @@ -61,8 +64,8 @@ GetOptions(
'detect-hangups!'=>\$kill_stale,
# allow-hangups is kept for backward compatibility.
'allow-hangups!'=>\$kill_stale,
'memlimit|m=i'=>\$memlimit,
'memlimit-rss|s=i'=>\$memlimit_rss,
'memlimit|m=s'=>\$memlimit,
'memlimit-rss|s=s'=>\$memlimit_rss,
'frequency|x=i'=>\$frequency,
'pattern|p=s'=>\$strpat,
'output|o=s'=>\$output,
Expand All @@ -76,6 +79,9 @@ GetOptions(

@ARGV or usage;

$memlimit = parse_memory_arg($memlimit);
$memlimit_rss = parse_memory_arg($memlimit_rss);

my $uinfo = get_patterns($strpat);

my $uwait = int (1_000_000 / $frequency);
Expand Down Expand Up @@ -446,7 +452,7 @@ sub print_uinfo
my $reason = shift;
# Print generic information to STDERR
my $ticks = $timeinfo->{ticks_stale} || 0;
printf STDERR "${id_str}%s CPU %.2f MEM %d MAXMEM %d STALE %d MAXMEM_RSS %d\n", $reason, $timeinfo->{total}, $meminfo, $maxmem, ceil($ticks/$frequency), $maxmem_rss if ($reason ne 'FINISHED') || $info_on_success;
printf STDERR "${id_str}%s CPU %.2f MEM %d KB %d MB %d GB MAXMEM %d KB %d MB %d GB STALE %d MAXMEM_RSS %d KB %d MB %d GB\n", $reason, $timeinfo->{total}, $meminfo, $meminfo/1024, $meminfo/1024/1024, $maxmem, $maxmem/1024, $maxmem/1024/1024, ceil($ticks/$frequency), $maxmem_rss, $maxmem_rss/1024, $maxmem_rss/1024/1024 if ($reason ne 'FINISHED') || $info_on_success;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not change the output format

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other ppl's software might depend on it, and also I find it a bit superfluous.


if (defined $output){
open(FIL,">>", $output) or die "Can't open output file: $!\n";
Expand Down Expand Up @@ -516,3 +522,25 @@ sub child_status_to_exit_code
return $child_retv >> 8;
}
}

# Allow memory arguments to specified as bytes, KB, MB, or GB.
sub parse_memory_arg
{
my ($mem) = @_;
if (defined($mem)) {
if ($mem =~ /^\d+$/) {
$mem = int($mem);
} elsif ($mem =~ /(^\d*\.{0,1}\d*)kb$/i) {
$mem = int($1);
} elsif ($mem =~ /(^\d*\.{0,1}\d*)mb$/i) {
$mem = int($1*1024);
} elsif ($mem =~ /(^\d*\.{0,1}\d*)gb$/i) {
$mem = int($1*1024*1024);
} else {
print STDERR "Error: Unrecognized memory argument: '$mem'.\n";
usage();
}
printf STDERR "mem : %d KB = %.1f MB = %.1f GB\n", $mem, $mem/1024., $mem/1024./1024. if $debug;
}
return $mem;
}