pg_regress: Save errno in emit_tap_output_v() and switch to %m
authorMichael Paquier <michael@paquier.xyz>
Thu, 4 Apr 2024 02:33:07 +0000 (11:33 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 4 Apr 2024 02:33:07 +0000 (11:33 +0900)
emit_tap_output_v() includes some fprintf() calls for some output
related to the TAP protocol, that may clobber errno and break %m.  This
commit makes the logging of pg_regress smarter by saving errno before
restoring it in vfprintf() where the input strings are used, removing
the need for strerror().  All logs are switched to %m rather than
strerror(), shaving some code.

This was not a problem until now as pg_regress.c did not use %m, but the
change is simple enough that we have no reason to not support this
placeholder, and that will avoid future mistakes if new logs that
include %m are added.

Author: Dagfinn Ilmari MannsÃ¥ker
Reviewed-by: Peter Eisentraunt, Michael Paquier
Discussion: https://postgr.es/m/87sf13jhuw.fsf@wibble.ilmari.org

src/test/regress/pg_regress.c

index 76f01c73f566b73272622e144ec978ad3e5c6951..06f6775fc65b082bfd252b3472c8380528add9ab 100644 (file)
@@ -341,6 +341,14 @@ emit_tap_output_v(TAPtype type, const char *fmt, va_list argp)
 {
        va_list         argp_logfile;
        FILE       *fp;
+       int                     save_errno;
+
+       /*
+        * The fprintf() calls used to output TAP-protocol elements might clobber
+        * errno, so save it here and restore it before vfprintf()-ing the user's
+        * format string, in case it contains %m placeholders.
+        */
+       save_errno = errno;
 
        /*
         * Diagnostic output will be hidden by prove unless printed to stderr. The
@@ -379,9 +387,13 @@ emit_tap_output_v(TAPtype type, const char *fmt, va_list argp)
                if (logfile)
                        fprintf(logfile, "# ");
        }
+       errno = save_errno;
        vfprintf(fp, fmt, argp);
        if (logfile)
+       {
+               errno = save_errno;
                vfprintf(logfile, fmt, argp_logfile);
+       }
 
        /*
         * If we are entering into a note with more details to follow, register
@@ -492,10 +504,7 @@ make_temp_sockdir(void)
 
        temp_sockdir = mkdtemp(template);
        if (temp_sockdir == NULL)
-       {
-               bail("could not create directory \"%s\": %s",
-                        template, strerror(errno));
-       }
+               bail("could not create directory \"%s\": %m", template);
 
        /* Stage file names for remove_temp().  Unsafe in a signal handler. */
        UNIXSOCK_PATH(sockself, port, temp_sockdir);
@@ -616,8 +625,7 @@ load_resultmap(void)
                /* OK if it doesn't exist, else complain */
                if (errno == ENOENT)
                        return;
-               bail("could not open file \"%s\" for reading: %s",
-                        buf, strerror(errno));
+               bail("could not open file \"%s\" for reading: %m", buf);
        }
 
        while (fgets(buf, sizeof(buf), f))
@@ -1046,10 +1054,7 @@ config_sspi_auth(const char *pgdata, const char *superuser_name)
 #define CW(cond)       \
        do { \
                if (!(cond)) \
-               { \
-                       bail("could not write to file \"%s\": %s", \
-                                fname, strerror(errno)); \
-               } \
+                       bail("could not write to file \"%s\": %m", fname); \
        } while (0)
 
        res = snprintf(fname, sizeof(fname), "%s/pg_hba.conf", pgdata);
@@ -1064,8 +1069,7 @@ config_sspi_auth(const char *pgdata, const char *superuser_name)
        hba = fopen(fname, "w");
        if (hba == NULL)
        {
-               bail("could not open file \"%s\" for writing: %s",
-                        fname, strerror(errno));
+               bail("could not open file \"%s\" for writing: %m", fname);
        }
        CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0);
        CW(fputs("host all all 127.0.0.1/32  sspi include_realm=1 map=regress\n",
@@ -1079,8 +1083,7 @@ config_sspi_auth(const char *pgdata, const char *superuser_name)
        ident = fopen(fname, "w");
        if (ident == NULL)
        {
-               bail("could not open file \"%s\" for writing: %s",
-                        fname, strerror(errno));
+               bail("could not open file \"%s\" for writing: %m", fname);
        }
        CW(fputs("# Configuration written by config_sspi_auth()\n", ident) >= 0);
 
@@ -1210,7 +1213,7 @@ spawn_process(const char *cmdline)
        pid = fork();
        if (pid == -1)
        {
-               bail("could not fork: %s", strerror(errno));
+               bail("could not fork: %m");
        }
        if (pid == 0)
        {
@@ -1226,7 +1229,7 @@ spawn_process(const char *cmdline)
                cmdline2 = psprintf("exec %s", cmdline);
                execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
                /* Not using the normal bail() here as we want _exit */
-               bail_noatexit("could not exec \"%s\": %s", shellprog, strerror(errno));
+               bail_noatexit("could not exec \"%s\": %m", shellprog);
        }
        /* in parent */
        return pid;
@@ -1262,8 +1265,7 @@ file_size(const char *file)
 
        if (!f)
        {
-               diag("could not open file \"%s\" for reading: %s",
-                        file, strerror(errno));
+               diag("could not open file \"%s\" for reading: %m", file);
                return -1;
        }
        fseek(f, 0, SEEK_END);
@@ -1284,8 +1286,7 @@ file_line_count(const char *file)
 
        if (!f)
        {
-               diag("could not open file \"%s\" for reading: %s",
-                        file, strerror(errno));
+               diag("could not open file \"%s\" for reading: %m", file);
                return -1;
        }
        while ((c = fgetc(f)) != EOF)
@@ -1325,9 +1326,7 @@ static void
 make_directory(const char *dir)
 {
        if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
-       {
-               bail("could not create directory \"%s\": %s", dir, strerror(errno));
-       }
+               bail("could not create directory \"%s\": %m", dir);
 }
 
 /*
@@ -1456,10 +1455,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
 
                alt_expectfile = get_alternative_expectfile(expectfile, i);
                if (!alt_expectfile)
-               {
-                       bail("Unable to check secondary comparison files: %s",
-                                strerror(errno));
-               }
+                       bail("Unable to check secondary comparison files: %m");
 
                if (!file_exists(alt_expectfile))
                {
@@ -1572,9 +1568,7 @@ wait_for_tests(PID_TYPE * pids, int *statuses, instr_time *stoptimes,
                p = wait(&exit_status);
 
                if (p == INVALID_PID)
-               {
-                       bail("failed to wait for subprocesses: %s", strerror(errno));
-               }
+                       bail("failed to wait for subprocesses: %m");
 #else
                DWORD           exit_status;
                int                     r;
@@ -1664,10 +1658,7 @@ run_schedule(const char *schedule, test_start_function startfunc,
 
        scf = fopen(schedule, "r");
        if (!scf)
-       {
-               bail("could not open file \"%s\" for reading: %s",
-                        schedule, strerror(errno));
-       }
+               bail("could not open file \"%s\" for reading: %m", schedule);
 
        while (fgets(scbuf, sizeof(scbuf), scf))
        {
@@ -1931,20 +1922,15 @@ open_result_files(void)
        logfilename = pg_strdup(file);
        logfile = fopen(logfilename, "w");
        if (!logfile)
-       {
-               bail("could not open file \"%s\" for writing: %s",
-                        logfilename, strerror(errno));
-       }
+               bail("could not open file \"%s\" for writing: %m", logfilename);
 
        /* create the diffs file as empty */
        snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
        difffilename = pg_strdup(file);
        difffile = fopen(difffilename, "w");
        if (!difffile)
-       {
-               bail("could not open file \"%s\" for writing: %s",
-                        difffilename, strerror(errno));
-       }
+               bail("could not open file \"%s\" for writing: %m", difffilename);
+
        /* we don't keep the diffs file open continuously */
        fclose(difffile);
 
@@ -2406,10 +2392,8 @@ regression_main(int argc, char *argv[],
                snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_instance);
                pg_conf = fopen(buf, "a");
                if (pg_conf == NULL)
-               {
-                       bail("could not open \"%s\" for adding extra config: %s",
-                                buf, strerror(errno));
-               }
+                       bail("could not open \"%s\" for adding extra config: %m", buf);
+
                fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
                fputs("log_autovacuum_min_duration = 0\n", pg_conf);
                fputs("log_checkpoints = on\n", pg_conf);
@@ -2427,8 +2411,8 @@ regression_main(int argc, char *argv[],
                        extra_conf = fopen(temp_config, "r");
                        if (extra_conf == NULL)
                        {
-                               bail("could not open \"%s\" to read extra config: %s",
-                                        temp_config, strerror(errno));
+                               bail("could not open \"%s\" to read extra config: %m",
+                                        temp_config);
                        }
                        while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
                                fputs(line_buf, pg_conf);
@@ -2503,7 +2487,7 @@ regression_main(int argc, char *argv[],
                                 outputdir);
                postmaster_pid = spawn_process(buf);
                if (postmaster_pid == INVALID_PID)
-                       bail("could not spawn postmaster: %s", strerror(errno));
+                       bail("could not spawn postmaster: %m");
 
                /*
                 * Wait till postmaster is able to accept connections; normally takes
@@ -2566,7 +2550,7 @@ regression_main(int argc, char *argv[],
                         */
 #ifndef WIN32
                        if (kill(postmaster_pid, SIGKILL) != 0 && errno != ESRCH)
-                               bail("could not kill failed postmaster: %s", strerror(errno));
+                               bail("could not kill failed postmaster: %m");
 #else
                        if (TerminateProcess(postmaster_pid, 255) == 0)
                                bail("could not kill failed postmaster: error code %lu",