In pgbench, when an error occurs during a benchmark run (SQL error, connection error, etc.) it just prints an error message and then proceeds to print the run summary normally and exits with status 0. So this is quite inconvenient, especially from a script.
The attached patch changes this so that it exits with status 1 and also prints a line below the summary advising that the results are incomplete. The test suite had, curiously, encoded the previous behavior, checking for exit status 0 vs 1 in various error situations. In this patch, I have just updated the expected results (which are all "1" now), but perhaps we should remove listing that individually and just check for nonzero in all cases somewhere centrally. -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From e269dccd449efffc83e53d7f1954818b44205935 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <pete...@gmx.net> Date: Tue, 3 Jul 2018 19:51:24 +0200 Subject: [PATCH] pgbench: Report errors during run better When an error occurs during a benchmark run, exit with a nonzero exit code and write a message at the end. Previously, it would just print the error message when it happened but then proceed to print the run summary normally and exit with status 0. --- src/bin/pgbench/pgbench.c | 10 +++- src/bin/pgbench/t/001_pgbench_with_server.pl | 51 ++++++++++---------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 41b756c089..19bd6b033f 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -4830,6 +4830,8 @@ main(int argc, char **argv) PGresult *res; char *env; + int exit_code = 0; + progname = get_progname(argv[0]); if (argc > 1) @@ -5570,6 +5572,9 @@ main(int argc, char **argv) (void) threadRun(thread); #endif /* ENABLE_THREAD_SAFETY */ + if (thread->state->state == CSTATE_ABORTED) + exit_code = 1; + /* aggregate thread level stats */ mergeSimpleStats(&stats.latency, &thread->stats.latency); mergeSimpleStats(&stats.lag, &thread->stats.lag); @@ -5594,7 +5599,10 @@ main(int argc, char **argv) INSTR_TIME_SUBTRACT(total_time, start_time); printResults(threads, &stats, total_time, conn_total_time, latency_late); - return 0; + if (exit_code != 0) + fprintf(stderr, "Run was aborted; the above results are incomplete.\n"); + + return exit_code; } static void * diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index 2fc021dde7..82e75c5f03 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -534,7 +534,7 @@ sub pgbench # SQL [ 'sql syntax error', - 0, + 1, [ qr{ERROR: syntax error}, qr{prepared statement .* does not exist} @@ -553,11 +553,11 @@ sub pgbench # SHELL [ - 'shell bad command', 0, + 'shell bad command', 1, [qr{\(shell\) .* meta-command failed}], q{\shell no-such-command} ], [ - 'shell undefined variable', 0, + 'shell undefined variable', 1, [qr{undefined variable ":nosuchvariable"}], q{-- undefined variable in shell \shell echo ::foo :nosuchvariable @@ -597,81 +597,81 @@ sub pgbench [qr{unexpected function name}], q{\set i noSuchFunction()} ], [ - 'set invalid variable name', 0, + 'set invalid variable name', 1, [qr{invalid variable name}], q{\set . 1} ], [ - 'set int overflow', 0, + 'set int overflow', 1, [qr{double to int overflow for 100}], q{\set i int(1E32)} ], - [ 'set division by zero', 0, [qr{division by zero}], q{\set i 1/0} ], + [ 'set division by zero', 1, [qr{division by zero}], q{\set i 1/0} ], [ - 'set bigint out of range', 0, + 'set bigint out of range', 1, [qr{bigint out of range}], q{\set i 9223372036854775808 / -1} ], [ 'set undefined variable', - 0, + 1, [qr{undefined variable "nosuchvariable"}], q{\set i :nosuchvariable} ], [ 'set unexpected char', 1, [qr{unexpected character .;.}], q{\set i ;} ], [ 'set too many args', - 0, + 1, [qr{too many function arguments}], q{\set i least(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)} ], [ - 'set empty random range', 0, + 'set empty random range', 1, [qr{empty range given to random}], q{\set i random(5,3)} ], [ 'set random range too large', - 0, + 1, [qr{random range is too large}], q{\set i random(-9223372036854775808, 9223372036854775807)} ], [ 'set gaussian param too small', - 0, + 1, [qr{gaussian param.* at least 2}], q{\set i random_gaussian(0, 10, 1.0)} ], [ 'set exponential param greater 0', - 0, + 1, [qr{exponential parameter must be greater }], q{\set i random_exponential(0, 10, 0.0)} ], [ 'set zipfian param to 1', - 0, + 1, [qr{zipfian parameter must be in range \(0, 1\) U \(1, \d+\]}], q{\set i random_zipfian(0, 10, 1)} ], [ 'set zipfian param too large', - 0, + 1, [qr{zipfian parameter must be in range \(0, 1\) U \(1, \d+\]}], q{\set i random_zipfian(0, 10, 1000000)} ], [ - 'set non numeric value', 0, + 'set non numeric value', 1, [qr{malformed variable "foo" value: "bla"}], q{\set i :foo + 1} ], [ 'set no expression', 1, [qr{syntax error}], q{\set i} ], [ 'set missing argument', 1, [qr{missing argument}i], q{\set} ], [ - 'set not a bool', 0, + 'set not a bool', 1, [qr{cannot coerce double to boolean}], q{\set b NOT 0.0} ], [ - 'set not an int', 0, + 'set not an int', 1, [qr{cannot coerce boolean to int}], q{\set i TRUE + 2} ], [ - 'set not a double', 0, + 'set not a double', 1, [qr{cannot coerce boolean to double}], q{\set d ln(TRUE)} ], [ @@ -681,7 +681,7 @@ sub pgbench q{\set i CASE TRUE THEN 1 ELSE 0 END} ], [ - 'set random error', 0, + 'set random error', 1, [qr{cannot coerce boolean to int}], q{\set b random(FALSE, TRUE)} ], [ @@ -695,18 +695,18 @@ sub pgbench # SETSHELL [ - 'setshell not an int', 0, + 'setshell not an int', 1, [qr{command must return an integer}], q{\setshell i echo -n one} ], [ 'setshell missing arg', 1, [qr{missing argument }], q{\setshell var} ], [ - 'setshell no such command', 0, + 'setshell no such command', 1, [qr{could not read result }], q{\setshell var no-such-command} ], # SLEEP [ - 'sleep undefined variable', 0, + 'sleep undefined variable', 1, [qr{sleep: undefined variable}], q{\sleep :nosuchvariable} ], [ @@ -729,7 +729,7 @@ sub pgbench ], [ 'misc empty script', 1, [qr{empty command list for script}], q{} ], [ - 'bad boolean', 0, + 'bad boolean', 1, [qr{malformed variable.*trueXXX}], q{\set b :badtrue or true} ],); @@ -737,12 +737,13 @@ sub pgbench for my $e (@errors) { my ($name, $status, $re, $script) = @$e; + $status != 0 or die; my $n = '001_pgbench_error_' . $name; $n =~ s/ /_/g; pgbench( '-n -t 1 -Dfoo=bla -Dnull=null -Dtrue=true -Done=1 -Dzero=0.0 -Dbadtrue=trueXXX -M prepared', $status, - [ $status ? qr{^$} : qr{processed: 0/1} ], + [], $re, 'pgbench script error: ' . $name, { $n => $script }); -- 2.18.0