pgbench: Improve error-handling in pgbench.
authorFujii Masao <fujii@postgresql.org>
Tue, 2 Nov 2021 13:49:57 +0000 (22:49 +0900)
committerFujii Masao <fujii@postgresql.org>
Tue, 2 Nov 2021 13:49:57 +0000 (22:49 +0900)
Previously failures of initial connection and logfile open caused pgbench
to proceed the benchmarking, report the incomplete results and exit with
status 2. It didn't make sense to proceed the benchmarking even when
pgbench could not start as prescribed.

This commit improves pgbench so that early errors that occur when
starting benchmark such as those failures should make pgbench exit
immediately with status 1.

Author: Yugo Nagata
Reviewed-by: Fabien COELHO, Kyotaro Horiguchi, Fujii Masao
Discussion: https://postgr.es/m/TYCPR01MB5870057375ACA8A73099C649F5349@TYCPR01MB5870.jpnprd01.prod.outlook.com

doc/src/sgml/ref/pgbench.sgml
src/bin/pgbench/pgbench.c

index 0f432767c25872c636065cb145e9d342024b2376..c71dab644cad58510c9a0f498fae3b74ceba270f 100644 (file)
@@ -904,10 +904,12 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
 
   <para>
    A successful run will exit with status 0.  Exit status 1 indicates static
-   problems such as invalid command-line options.  Errors during the run such
-   as database errors or problems in the script will result in exit status 2.
-   In the latter case, <application>pgbench</application> will print partial
-   results.
+   problems such as invalid command-line options or internal errors which
+   are supposed to never occur.  Early errors that occur when starting
+   benchmark such as initial connection failures also exit with status 1.
+   Errors during the run such as database errors or problems in the script
+   will result in exit status 2. In the latter case,
+   <application>pgbench</application> will print partial results.
   </para>
  </refsect1>
 
index d17f69333f41901c7231deec81dadb73275ff370..0dfb625a8884f499f503df64e67fd66b383c5aa3 100644 (file)
@@ -3181,6 +3181,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
 
                    if ((st->con = doConnect()) == NULL)
                    {
+                       /*
+                        * as the bench is already running, we do not abort
+                        * the process
+                        */
                        pg_log_error("client %d aborted while establishing connection", st->id);
                        st->state = CSTATE_ABORTED;
                        break;
@@ -4456,7 +4460,10 @@ runInitSteps(const char *initialize_steps)
    initPQExpBuffer(&stats);
 
    if ((con = doConnect()) == NULL)
+   {
+       pg_log_fatal("could not create connection for initialization");
        exit(1);
+   }
 
    setup_cancel_handler(NULL);
    SetCancelConn(con);
@@ -6399,7 +6406,10 @@ main(int argc, char **argv)
    /* opening connection... */
    con = doConnect();
    if (con == NULL)
+   {
+       pg_log_fatal("could not create connection for setup");
        exit(1);
+   }
 
    /* report pgbench and server versions */
    printVersion(con);
@@ -6625,7 +6635,7 @@ threadRun(void *arg)
        if (thread->logfile == NULL)
        {
            pg_log_fatal("could not open logfile \"%s\": %m", logpath);
-           goto done;
+           exit(1);
        }
    }
 
@@ -6650,16 +6660,10 @@ threadRun(void *arg)
        {
            if ((state[i].con = doConnect()) == NULL)
            {
-               /*
-                * On connection failure, we meet the barrier here in place of
-                * GO before proceeding to the "done" path which will cleanup,
-                * so as to avoid locking the process.
-                *
-                * It is unclear whether it is worth doing anything rather
-                * than coldly exiting with an error message.
-                */
-               THREAD_BARRIER_WAIT(&barrier);
-               goto done;
+               /* coldly abort on initial connection failure */
+               pg_log_fatal("could not create connection for client %d",
+                            state[i].id);
+               exit(1);
            }
        }
    }