pg_upgrade's exec_prog() coding improvement
Hi,
I've been bitten twice by exec_prog()s API, so here's a patch to try to
make it a bit harder to misuse.
There are two main changes here; one is to put the logfile option as the
first argument; then comes a bool, then the format string. This means
you get a warning if you pass the wrong number of arguments before the
format; previously I mis-merged in the KEY SHARE patch so that I was
passing the log file as format, and the compiler didn't complain at all.
The other interesting change I did was move the responsibility of adding
SYSTEMQUOTE and the ">> %s 2>&1" redirections to exec_prog itself,
reducing clutter in the caller. This makes the callers a lot easier to
read.
One other minor change I did was split it in two versions: a simpler one
with less frammishes, that doesn't let you supply an alternative log
file and doesn't return a status value. This is used for all but one of
the callers; only that one caller was interested in the result value
anyway. And that caller is also the only one that passes an
opt_log_file other than NULL, so I removed that from the simple version.
Lastly, I removed the is_priv boolean, which seems pretty pointless;
just made all calls set the umask inconditionally. The only caller
doing this was the cp/xcopy call, and I don't see any reason for this to
be different from other callers.
This makes pg_upgrade a bit more readable.
If anyone can test this on Windows I would be appreciate it.
One problem with this is that I get this warning:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c: In function ‘s_exec_prog’:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]
I have no idea how to silence that. Ideas?
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Attachments:
upgrade_execprog.patchapplication/octet-stream; name=upgrade_execprog.patchDownload
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index aa896b5..4e22e88 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -183,13 +183,10 @@ issue_warnings(char *sequence_script_file_name)
if (sequence_script_file_name)
{
prep_status("Adjusting sequences");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
new_cluster.bindir, new_cluster.port, os_info.user,
- sequence_script_file_name, UTILITY_LOG_FILE);
+ sequence_script_file_name);
unlink(sequence_script_file_name);
check_ok();
}
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
index 07a3b54..da3901d 100644
--- a/contrib/pg_upgrade/dump.c
+++ b/contrib/pg_upgrade/dump.c
@@ -23,12 +23,10 @@ generate_old_dump(void)
* --binary-upgrade records the width of dropped columns in pg_class, and
* restores the frozenid's for databases and relations.
*/
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --username \"%s\" "
- "--schema-only --binary-upgrade %s > \"%s\" 2>> \"%s\""
- SYSTEMQUOTE, new_cluster.bindir, old_cluster.port, os_info.user,
- log_opts.verbose ? "--verbose" : "",
- ALL_DUMP_FILE, UTILITY_LOG_FILE);
+ exec_prog(UTILITY_LOG_FILE, true,
+ "\"%s/pg_dumpall\" --port %d --username \"%s\" --schema-only --binary-upgrade %s -f %s",
+ new_cluster.bindir, old_cluster.port, os_info.user,
+ log_opts.verbose ? "--verbose" : "", ALL_DUMP_FILE);
check_ok();
}
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 6f993df..8b68794 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -15,6 +15,8 @@
#include <unistd.h>
#include <sys/types.h>
+static bool s_exec_prog(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *fmt, va_list args);
static void check_data_dir(const char *pg_data);
static void check_bin_dir(ClusterInfo *cluster);
static void validate_exec(const char *dir, const char *cmdName);
@@ -23,83 +25,118 @@ static void validate_exec(const char *dir, const char *cmdName);
static int win32_check_directory_write_permissions(void);
#endif
+/*
+ * exec_prog_ext
+ * Execute an external program and report errors
+ *
+ * Formats a command from the given argument list, logs it to the log file,
+ * and attempts to execute that command. If the command executes
+ * successfully, exec_prog_ext() returns true.
+ *
+ * If the command fails, an error message is saved to the specified log_file.
+ * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
+ * terminates; otherwise it is just reported as PG_REPORT and exec_prog returns
+ * false.
+ */
+bool
+exec_prog_ext(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *cmd,...)
+{
+ va_list ap;
+ bool retval;
+
+ va_start(ap, cmd);
+ retval = s_exec_prog(log_file, opt_log_file, throw_error, cmd, ap);
+ va_end(ap);
+
+ return retval;
+}
/*
* exec_prog()
+ * Execute an external program with stdout/stderr redirected, and report
+ * errors
*
- * Formats a command from the given argument list and executes that
- * command. If the command executes, exec_prog() returns 1 otherwise
- * exec_prog() logs an error message and returns 0. Either way, the command
- * line to be executed is saved to the specified log file.
+ * Formats a command from the given argument list, logs it to the log file,
+ * and attempts to execute that command. If the command executes
+ * successfully, exec_prog() returns.
*
- * If throw_error is TRUE, this function will throw a PG_FATAL error
- * instead of returning should an error occur. The command it appended
- * to log_file; opt_log_file is used in error messages.
+ * If the command fails, an error message is saved to the specified log_file.
+ * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
+ * terminates; otherwise it is just reported as PG_REPORT.
*/
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
- const char *opt_log_file, const char *fmt,...)
+void
+exec_prog(const char *log_file, bool throw_error, const char *cmd,...)
+{
+ va_list ap;
+
+ va_start(ap, cmd);
+ s_exec_prog(log_file, NULL, throw_error, cmd, ap);
+ va_end(ap);
+}
+
+/*
+ * s_exec_prog
+ * va_list version of the above
+ */
+static bool
+s_exec_prog(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *fmt, va_list args)
{
- va_list args;
int result;
- int retval;
- char cmd[MAXPGPATH];
+ int written;
+#define MAXCMDLEN (2 * MAXPGPATH)
+ char cmd[MAXCMDLEN];
mode_t old_umask = 0;
FILE *log;
- if (is_priv)
- old_umask = umask(S_IRWXG | S_IRWXO);
+ old_umask = umask(S_IRWXG | S_IRWXO);
- va_start(args, fmt);
- vsnprintf(cmd, MAXPGPATH, fmt, args);
- va_end(args);
+ written = strlcat(cmd, SYSTEMQUOTE, strlen(SYSTEMQUOTE));
+ written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, args);
+ snprintf(cmd + written, MAXCMDLEN - written,
+ " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
pg_log(PG_VERBOSE, "%s\n", cmd);
fprintf(log, "command: %s\n", cmd);
+
/*
- * In Windows, we must close then reopen the log file so the file is
- * not open while the command is running, or we get a share violation.
+ * In Windows, we must close the log file at this point so the file is not
+ * open while the command is running, or we get a share violation.
*/
fclose(log);
result = system(cmd);
- if (is_priv)
- umask(old_umask);
+ umask(old_umask);
if (result != 0)
{
- char opt_string[MAXPGPATH];
-
- /* Create string for optional second log file */
- if (opt_log_file)
- snprintf(opt_string, sizeof(opt_string), " or \"%s\"", opt_log_file);
- else
- opt_string[0] = '\0';
-
report_status(PG_REPORT, "*failure*");
fflush(stdout);
pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
- pg_log(throw_error ? PG_FATAL : PG_REPORT,
- "Consult the last few lines of \"%s\"%s for\n"
- "the probable cause of the failure.\n",
- log_file, opt_string);
- retval = 1;
+ if (opt_log_file)
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" or \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file, opt_log_file);
+ else
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file);
}
- else
- retval = 0;
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
fprintf(log, "\n\n");
fclose(log);
- return retval;
+ return result == 0;
}
-
/*
* is_server_running()
*
@@ -128,7 +165,6 @@ is_server_running(const char *datadir)
return true;
}
-
/*
* verify_directories()
*
diff --git a/contrib/pg_upgrade/file.c b/contrib/pg_upgrade/file.c
index 5509670..a5d92c6 100644
--- a/contrib/pg_upgrade/file.c
+++ b/contrib/pg_upgrade/file.c
@@ -103,10 +103,10 @@ copyAndUpdateFile(pageCnvCtx *pageConverter,
/*
* linkAndUpdateFile()
*
- * Creates a symbolic link between the given relation files. We use
+ * Creates a hard link between the given relation files. We use
* this function to perform a true in-place update. If the on-disk
* format of the new cluster is bit-for-bit compatible with the on-disk
- * format of the old cluster, we can simply symlink each relation
+ * format of the old cluster, we can simply link each relation
* instead of copying the data from the old cluster to the new cluster.
*/
const char *
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index eff1a08..a618f30 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -140,11 +140,10 @@ main(int argc, char **argv)
* because there is no need to have the schema load use new oids.
*/
prep_status("Setting next OID for new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, true,
+ "\"%s/pg_resetxlog\" -o %u \"%s\"",
new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ new_cluster.pgdata);
check_ok();
create_script_for_cluster_analyze(&analyze_script_file_name);
@@ -211,11 +210,10 @@ prepare_new_cluster(void)
* --analyze so autovacuum doesn't update statistics later
*/
prep_status("Analyzing all rows in the new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
- "--all --analyze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, true,
+ "\"%s/vacuumdb\" --port %d --username \"%s\" --all --analyze %s",
new_cluster.bindir, new_cluster.port, os_info.user,
- log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+ log_opts.verbose ? "--verbose" : "");
check_ok();
/*
@@ -225,11 +223,10 @@ prepare_new_cluster(void)
* later.
*/
prep_status("Freezing all rows on the new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
- "--all --freeze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, true,
+ "\"%s/vacuumdb\" --port %d --username \"%s\" --all --freeze %s",
new_cluster.bindir, new_cluster.port, os_info.user,
- log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+ log_opts.verbose ? "--verbose" : "");
check_ok();
get_pg_database_relfilenode(&new_cluster);
@@ -263,14 +260,10 @@ prepare_new_databases(void)
* support functions in template1 but pg_dumpall creates database using
* the template0 template.
*/
- exec_prog(true, true, RESTORE_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- /* --no-psqlrc prevents AUTOCOMMIT=off */
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(RESTORE_LOG_FILE, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
new_cluster.bindir, new_cluster.port, os_info.user,
- GLOBALS_DUMP_FILE, RESTORE_LOG_FILE);
+ GLOBALS_DUMP_FILE);
check_ok();
/* we load this to get a current list of databases */
@@ -296,13 +289,10 @@ create_new_objects(void)
check_ok();
prep_status("Restoring database schema to new cluster");
- exec_prog(true, true, RESTORE_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(RESTORE_LOG_FILE, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
new_cluster.bindir, new_cluster.port, os_info.user,
- DB_DUMP_FILE, RESTORE_LOG_FILE);
+ DB_DUMP_FILE);
check_ok();
/* regenerate now that we have objects in the databases */
@@ -331,16 +321,14 @@ copy_subdir_files(char *subdir)
prep_status("Copying old %s to new server", subdir);
- exec_prog(true, false, UTILITY_LOG_FILE, NULL,
+ exec_prog(UTILITY_LOG_FILE, true,
#ifndef WIN32
- SYSTEMQUOTE "%s \"%s\" \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
- "cp -Rf",
+ "cp -Rf \"%s\" \"%s\"",
#else
/* flags: everything, no confirm, quiet, overwrite read-only */
- SYSTEMQUOTE "%s \"%s\" \"%s\\\" >> \"%s\" 2>&1" SYSTEMQUOTE,
- "xcopy /e /y /q /r",
+ "xcopy /e /y /q /r \"%s\" \"%s\\\"",
#endif
- old_path, new_path, UTILITY_LOG_FILE);
+ old_path, new_path);
check_ok();
}
@@ -353,22 +341,18 @@ copy_clog_xlog_xid(void)
/* set the next transaction id of the new cluster */
prep_status("Setting next transaction ID for new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE
- "\"%s/pg_resetxlog\" -f -x %u \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE, new_cluster.bindir,
- old_cluster.controldata.chkpnt_nxtxid,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ exec_prog(UTILITY_LOG_FILE, true,
+ "\"%s/pg_resetxlog\" -f -x %u \"%s\"",
+ new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid,
+ new_cluster.pgdata);
check_ok();
/* now reset the wal archives in the new cluster */
prep_status("Resetting WAL archives");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE
- "\"%s/pg_resetxlog\" -l %s \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE, new_cluster.bindir,
+ exec_prog(UTILITY_LOG_FILE, true,
+ "\"%s/pg_resetxlog\" -l %s \"%s\"", new_cluster.bindir,
old_cluster.controldata.nextxlogfile,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ new_cluster.pgdata);
check_ok();
}
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index affee7a..cc8ae4e 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -316,10 +316,15 @@ void split_old_dump(void);
/* exec.c */
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
- const char *opt_log_file, const char *cmd,...)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 5, 6)));
+#define EXEC_PSQL_ARGS "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"
+void
+exec_prog(const char *log_file, bool throw_error, const char *cmd,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
+bool
+exec_prog_ext(const char *log_file, const char *opt_log_file,
+ bool throw_error,
+ const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 4, 5)));
void verify_directories(void);
bool is_server_running(const char *datadir);
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
index e94a897..3d028cd 100644
--- a/contrib/pg_upgrade/server.c
+++ b/contrib/pg_upgrade/server.c
@@ -143,7 +143,7 @@ start_postmaster(ClusterInfo *cluster)
char cmd[MAXPGPATH];
PGconn *conn;
bool exit_hook_registered = false;
- int pg_ctl_return = 0;
+ bool pg_ctl_return = false;
if (!exit_hook_registered)
{
@@ -159,23 +159,24 @@ start_postmaster(ClusterInfo *cluster)
* not touch them.
*/
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
- "-o \"-p %d %s %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
+ "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s\" start",
cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
(cluster->controldata.cat_ver >=
BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
"-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
- cluster->pgopts ? cluster->pgopts : "", SERVER_START_LOG_FILE);
+ cluster->pgopts ? cluster->pgopts : "");
/*
* Don't throw an error right away, let connecting throw the error because
* it might supply a reason for the failure.
*/
- pg_ctl_return = exec_prog(false, true, SERVER_START_LOG_FILE,
- /* pass both file names if the differ */
- (strcmp(SERVER_LOG_FILE, SERVER_START_LOG_FILE) != 0) ?
- SERVER_LOG_FILE : NULL,
- "%s", cmd);
+ pg_ctl_return = exec_prog_ext(SERVER_START_LOG_FILE,
+ /* pass both file names if the differ */
+ (strcmp(SERVER_LOG_FILE,
+ SERVER_START_LOG_FILE) != 0) ?
+ SERVER_LOG_FILE : NULL,
+ false,
+ "%s", cmd);
/* Check to see if we can connect to the server; if not, report it. */
if ((conn = get_db_conn(cluster, "template1")) == NULL ||
@@ -191,7 +192,7 @@ start_postmaster(ClusterInfo *cluster)
PQfinish(conn);
/* If the connection didn't fail, fail now */
- if (pg_ctl_return != 0)
+ if (!pg_ctl_return)
pg_log(PG_FATAL, "pg_ctl failed to start the %s server, or connection failed\n",
CLUSTER_NAME(cluster));
@@ -202,7 +203,6 @@ start_postmaster(ClusterInfo *cluster)
void
stop_postmaster(bool fast)
{
- char cmd[MAXPGPATH];
ClusterInfo *cluster;
if (os_info.running_cluster == &old_cluster)
@@ -212,14 +212,11 @@ stop_postmaster(bool fast)
else
return; /* no cluster running */
- snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" "
- "%s stop >> \"%s\" 2>&1" SYSTEMQUOTE,
- cluster->bindir, cluster->pgconfig,
- cluster->pgopts ? cluster->pgopts : "",
- fast ? "-m fast" : "", SERVER_STOP_LOG_FILE);
-
- exec_prog(fast ? false : true, true, SERVER_STOP_LOG_FILE, NULL, "%s", cmd);
+ exec_prog(SERVER_STOP_LOG_FILE, !fast,
+ "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
+ cluster->bindir, cluster->pgconfig,
+ cluster->pgopts ? cluster->pgopts : "",
+ fast ? "-m fast" : "");
os_info.running_cluster = NULL;
}
On 23.08.2012 23:07, Alvaro Herrera wrote:
One problem with this is that I get this warning:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c: In function ‘s_exec_prog’:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]I have no idea how to silence that. Ideas?
You can do what the warning suggests, and tell the compiler that
exec_prog takes printf-like arguments. See elog.h for an example of that:
extern int
errmsg(const char *fmt,...)
/* This extension allows gcc to check the format string for consistency with
the supplied arguments. */
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
On 23.08.2012 23:07, Alvaro Herrera wrote:
One problem with this is that I get this warning:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c: In function ‘s_exec_prog’:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]I have no idea how to silence that. Ideas?
You can do what the warning suggests, and tell the compiler that
exec_prog takes printf-like arguments.
exec_prog already has such decoration, and Alvaro's patch doesn't remove
it. So the question is, exactly what the heck does that warning mean?
regards, tom lane
On Fri, Aug 24, 2012 at 10:08:58AM -0400, Tom Lane wrote:
Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
On 23.08.2012 23:07, Alvaro Herrera wrote:
One problem with this is that I get this warning:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c: In function ‘s_exec_prog’:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]I have no idea how to silence that. Ideas?
You can do what the warning suggests, and tell the compiler that
exec_prog takes printf-like arguments.exec_prog already has such decoration, and Alvaro's patch doesn't remove
it. So the question is, exactly what the heck does that warning mean?
It sounds like it is suggestioning to use more specific attribute
decoration. This might be relevant:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-Wmissing-format-attribute
Warn about function pointers that might be candidates for format
attributes. Note these are only possible candidates, not absolute ones.
GCC guesses that function pointers with format attributes that are used
in assignment, initialization, parameter passing or return statements
should have a corresponding format attribute in the resulting type. I.e.
the left-hand side of the assignment or initialization, the type of the
parameter variable, or the return type of the containing function
respectively should also have a format attribute to avoid the warning.
GCC also warns about function definitions that might be candidates
for format attributes. Again, these are only possible candidates. GCC
guesses that format attributes might be appropriate for any function
that calls a function like vprintf or vscanf, but this might not always
be the case, and some functions for which format attributes are
appropriate may not be detected.
and I see this option enabled in configure.in.
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ It's impossible for everything to be true. +
Bruce Momjian <bruce@momjian.us> writes:
It sounds like it is suggestioning to use more specific attribute
decoration. This might be relevant:
-Wmissing-format-attribute
Warn about function pointers that might be candidates for format
attributes. Note these are only possible candidates, not absolute ones.
GCC guesses that function pointers with format attributes that are used
in assignment, initialization, parameter passing or return statements
should have a corresponding format attribute in the resulting type. I.e.
the left-hand side of the assignment or initialization, the type of the
parameter variable, or the return type of the containing function
respectively should also have a format attribute to avoid the warning.
GCC also warns about function definitions that might be candidates
for format attributes. Again, these are only possible candidates. GCC
guesses that format attributes might be appropriate for any function
that calls a function like vprintf or vscanf, but this might not always
be the case, and some functions for which format attributes are
appropriate may not be detected.
and I see this option enabled in configure.in.
Hm. I'm a bit dubious about enabling warnings that are so admittedly
heuristic as this. They admit that the warnings might be wrong, and
yet document no way to shut them up. I think we might be better advised
to not enable this warning.
regards, tom lane
Actually it seems better to just get rid of the extra varargs function
and just have a single exec_prog. The extra NULL argument is not
troublesome enough, it seems. Updated version attached.
Again, win32 testing would be welcome. Sadly, buildfarm does not run
pg_upgrade's "make check".
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Attachments:
upgrade_execprog-2.patchapplication/octet-stream; name=upgrade_execprog-2.patchDownload
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index aa896b5..0fec73e 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -183,13 +183,10 @@ issue_warnings(char *sequence_script_file_name)
if (sequence_script_file_name)
{
prep_status("Adjusting sequences");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
new_cluster.bindir, new_cluster.port, os_info.user,
- sequence_script_file_name, UTILITY_LOG_FILE);
+ sequence_script_file_name);
unlink(sequence_script_file_name);
check_ok();
}
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
index 07a3b54..cfc4017 100644
--- a/contrib/pg_upgrade/dump.c
+++ b/contrib/pg_upgrade/dump.c
@@ -23,12 +23,11 @@ generate_old_dump(void)
* --binary-upgrade records the width of dropped columns in pg_class, and
* restores the frozenid's for databases and relations.
*/
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --username \"%s\" "
- "--schema-only --binary-upgrade %s > \"%s\" 2>> \"%s\""
- SYSTEMQUOTE, new_cluster.bindir, old_cluster.port, os_info.user,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_dumpall\" --port %d --username \"%s\" --schema-only --binary-upgrade %s -f %s",
+ new_cluster.bindir, old_cluster.port, os_info.user,
log_opts.verbose ? "--verbose" : "",
- ALL_DUMP_FILE, UTILITY_LOG_FILE);
+ ALL_DUMP_FILE);
check_ok();
}
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 6f993df..45fbea0 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -26,77 +26,77 @@ static int win32_check_directory_write_permissions(void);
/*
* exec_prog()
+ * Execute an external program with stdout/stderr redirected, and report
+ * errors
*
- * Formats a command from the given argument list and executes that
- * command. If the command executes, exec_prog() returns 1 otherwise
- * exec_prog() logs an error message and returns 0. Either way, the command
- * line to be executed is saved to the specified log file.
+ * Formats a command from the given argument list, logs it to the log file,
+ * and attempts to execute that command. If the command executes
+ * successfully, exec_prog() returns true.
*
- * If throw_error is TRUE, this function will throw a PG_FATAL error
- * instead of returning should an error occur. The command it appended
- * to log_file; opt_log_file is used in error messages.
+ * If the command fails, an error message is saved to the specified log_file.
+ * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
+ * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
+ * returns false.
*/
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
- const char *opt_log_file, const char *fmt,...)
+bool
+exec_prog(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *fmt,...)
{
- va_list args;
int result;
- int retval;
- char cmd[MAXPGPATH];
+ int written;
+#define MAXCMDLEN (2 * MAXPGPATH)
+ char cmd[MAXCMDLEN];
mode_t old_umask = 0;
FILE *log;
+ va_list ap;
- if (is_priv)
- old_umask = umask(S_IRWXG | S_IRWXO);
+ old_umask = umask(S_IRWXG | S_IRWXO);
- va_start(args, fmt);
- vsnprintf(cmd, MAXPGPATH, fmt, args);
- va_end(args);
+ written = strlcat(cmd, SYSTEMQUOTE, strlen(SYSTEMQUOTE));
+ va_start(ap, fmt);
+ written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
+ va_end(ap);
+ snprintf(cmd + written, MAXCMDLEN - written,
+ " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
pg_log(PG_VERBOSE, "%s\n", cmd);
fprintf(log, "command: %s\n", cmd);
+
/*
- * In Windows, we must close then reopen the log file so the file is
- * not open while the command is running, or we get a share violation.
+ * In Windows, we must close the log file at this point so the file is not
+ * open while the command is running, or we get a share violation.
*/
fclose(log);
result = system(cmd);
- if (is_priv)
- umask(old_umask);
+ umask(old_umask);
if (result != 0)
{
- char opt_string[MAXPGPATH];
-
- /* Create string for optional second log file */
- if (opt_log_file)
- snprintf(opt_string, sizeof(opt_string), " or \"%s\"", opt_log_file);
- else
- opt_string[0] = '\0';
-
report_status(PG_REPORT, "*failure*");
fflush(stdout);
pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
- pg_log(throw_error ? PG_FATAL : PG_REPORT,
- "Consult the last few lines of \"%s\"%s for\n"
- "the probable cause of the failure.\n",
- log_file, opt_string);
- retval = 1;
+ if (opt_log_file)
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" or \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file, opt_log_file);
+ else
+ pg_log(throw_error ? PG_FATAL : PG_REPORT,
+ "Consult the last few lines of \"%s\" for\n"
+ "the probable cause of the failure.\n",
+ log_file);
}
- else
- retval = 0;
if ((log = fopen_priv(log_file, "a+")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
fprintf(log, "\n\n");
fclose(log);
- return retval;
+ return result == 0;
}
diff --git a/contrib/pg_upgrade/file.c b/contrib/pg_upgrade/file.c
index 5509670..a5d92c6 100644
--- a/contrib/pg_upgrade/file.c
+++ b/contrib/pg_upgrade/file.c
@@ -103,10 +103,10 @@ copyAndUpdateFile(pageCnvCtx *pageConverter,
/*
* linkAndUpdateFile()
*
- * Creates a symbolic link between the given relation files. We use
+ * Creates a hard link between the given relation files. We use
* this function to perform a true in-place update. If the on-disk
* format of the new cluster is bit-for-bit compatible with the on-disk
- * format of the old cluster, we can simply symlink each relation
+ * format of the old cluster, we can simply link each relation
* instead of copying the data from the old cluster to the new cluster.
*/
const char *
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index eff1a08..c47c8bb 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -140,11 +140,10 @@ main(int argc, char **argv)
* because there is no need to have the schema load use new oids.
*/
prep_status("Setting next OID for new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_resetxlog\" -o %u \"%s\"",
new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ new_cluster.pgdata);
check_ok();
create_script_for_cluster_analyze(&analyze_script_file_name);
@@ -211,11 +210,10 @@ prepare_new_cluster(void)
* --analyze so autovacuum doesn't update statistics later
*/
prep_status("Analyzing all rows in the new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
- "--all --analyze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/vacuumdb\" --port %d --username \"%s\" --all --analyze %s",
new_cluster.bindir, new_cluster.port, os_info.user,
- log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+ log_opts.verbose ? "--verbose" : "");
check_ok();
/*
@@ -225,11 +223,10 @@ prepare_new_cluster(void)
* later.
*/
prep_status("Freezing all rows on the new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
- "--all --freeze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/vacuumdb\" --port %d --username \"%s\" --all --freeze %s",
new_cluster.bindir, new_cluster.port, os_info.user,
- log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+ log_opts.verbose ? "--verbose" : "");
check_ok();
get_pg_database_relfilenode(&new_cluster);
@@ -263,14 +260,10 @@ prepare_new_databases(void)
* support functions in template1 but pg_dumpall creates database using
* the template0 template.
*/
- exec_prog(true, true, RESTORE_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- /* --no-psqlrc prevents AUTOCOMMIT=off */
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(RESTORE_LOG_FILE, NULL, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
new_cluster.bindir, new_cluster.port, os_info.user,
- GLOBALS_DUMP_FILE, RESTORE_LOG_FILE);
+ GLOBALS_DUMP_FILE);
check_ok();
/* we load this to get a current list of databases */
@@ -296,13 +289,10 @@ create_new_objects(void)
check_ok();
prep_status("Restoring database schema to new cluster");
- exec_prog(true, true, RESTORE_LOG_FILE, NULL,
- SYSTEMQUOTE "\"%s/psql\" --echo-queries "
- "--set ON_ERROR_STOP=on "
- "--no-psqlrc --port %d --username \"%s\" "
- "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
+ exec_prog(RESTORE_LOG_FILE, NULL, true,
+ "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
new_cluster.bindir, new_cluster.port, os_info.user,
- DB_DUMP_FILE, RESTORE_LOG_FILE);
+ DB_DUMP_FILE);
check_ok();
/* regenerate now that we have objects in the databases */
@@ -331,16 +321,14 @@ copy_subdir_files(char *subdir)
prep_status("Copying old %s to new server", subdir);
- exec_prog(true, false, UTILITY_LOG_FILE, NULL,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
#ifndef WIN32
- SYSTEMQUOTE "%s \"%s\" \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
- "cp -Rf",
+ "cp -Rf \"%s\" \"%s\"",
#else
/* flags: everything, no confirm, quiet, overwrite read-only */
- SYSTEMQUOTE "%s \"%s\" \"%s\\\" >> \"%s\" 2>&1" SYSTEMQUOTE,
- "xcopy /e /y /q /r",
+ "xcopy /e /y /q /r \"%s\" \"%s\\\"",
#endif
- old_path, new_path, UTILITY_LOG_FILE);
+ old_path, new_path);
check_ok();
}
@@ -353,22 +341,18 @@ copy_clog_xlog_xid(void)
/* set the next transaction id of the new cluster */
prep_status("Setting next transaction ID for new cluster");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE
- "\"%s/pg_resetxlog\" -f -x %u \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE, new_cluster.bindir,
- old_cluster.controldata.chkpnt_nxtxid,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_resetxlog\" -f -x %u \"%s\"",
+ new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid,
+ new_cluster.pgdata);
check_ok();
/* now reset the wal archives in the new cluster */
prep_status("Resetting WAL archives");
- exec_prog(true, true, UTILITY_LOG_FILE, NULL,
- SYSTEMQUOTE
- "\"%s/pg_resetxlog\" -l %s \"%s\" >> \"%s\" 2>&1"
- SYSTEMQUOTE, new_cluster.bindir,
+ exec_prog(UTILITY_LOG_FILE, NULL, true,
+ "\"%s/pg_resetxlog\" -l %s \"%s\"", new_cluster.bindir,
old_cluster.controldata.nextxlogfile,
- new_cluster.pgdata, UTILITY_LOG_FILE);
+ new_cluster.pgdata);
check_ok();
}
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index affee7a..5ee9a34 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -316,10 +316,10 @@ void split_old_dump(void);
/* exec.c */
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
- const char *opt_log_file, const char *cmd,...)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 5, 6)));
+#define EXEC_PSQL_ARGS "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"
+bool exec_prog(const char *log_file, const char *opt_log_file,
+ bool throw_error, const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 4, 5)));
void verify_directories(void);
bool is_server_running(const char *datadir);
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
index e94a897..8f2d3a6 100644
--- a/contrib/pg_upgrade/server.c
+++ b/contrib/pg_upgrade/server.c
@@ -143,7 +143,7 @@ start_postmaster(ClusterInfo *cluster)
char cmd[MAXPGPATH];
PGconn *conn;
bool exit_hook_registered = false;
- int pg_ctl_return = 0;
+ bool pg_ctl_return = false;
if (!exit_hook_registered)
{
@@ -159,22 +159,23 @@ start_postmaster(ClusterInfo *cluster)
* not touch them.
*/
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
- "-o \"-p %d %s %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
+ "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s\" start",
cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
(cluster->controldata.cat_ver >=
BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
"-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
- cluster->pgopts ? cluster->pgopts : "", SERVER_START_LOG_FILE);
+ cluster->pgopts ? cluster->pgopts : "");
/*
* Don't throw an error right away, let connecting throw the error because
* it might supply a reason for the failure.
*/
- pg_ctl_return = exec_prog(false, true, SERVER_START_LOG_FILE,
- /* pass both file names if the differ */
- (strcmp(SERVER_LOG_FILE, SERVER_START_LOG_FILE) != 0) ?
+ pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
+ /* pass both file names if the differ */
+ (strcmp(SERVER_LOG_FILE,
+ SERVER_START_LOG_FILE) != 0) ?
SERVER_LOG_FILE : NULL,
+ false,
"%s", cmd);
/* Check to see if we can connect to the server; if not, report it. */
@@ -191,7 +192,7 @@ start_postmaster(ClusterInfo *cluster)
PQfinish(conn);
/* If the connection didn't fail, fail now */
- if (pg_ctl_return != 0)
+ if (!pg_ctl_return)
pg_log(PG_FATAL, "pg_ctl failed to start the %s server, or connection failed\n",
CLUSTER_NAME(cluster));
@@ -202,7 +203,6 @@ start_postmaster(ClusterInfo *cluster)
void
stop_postmaster(bool fast)
{
- char cmd[MAXPGPATH];
ClusterInfo *cluster;
if (os_info.running_cluster == &old_cluster)
@@ -212,14 +212,11 @@ stop_postmaster(bool fast)
else
return; /* no cluster running */
- snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" "
- "%s stop >> \"%s\" 2>&1" SYSTEMQUOTE,
- cluster->bindir, cluster->pgconfig,
- cluster->pgopts ? cluster->pgopts : "",
- fast ? "-m fast" : "", SERVER_STOP_LOG_FILE);
-
- exec_prog(fast ? false : true, true, SERVER_STOP_LOG_FILE, NULL, "%s", cmd);
+ exec_prog(SERVER_STOP_LOG_FILE, NULL, !fast,
+ "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
+ cluster->bindir, cluster->pgconfig,
+ cluster->pgopts ? cluster->pgopts : "",
+ fast ? "-m fast" : "");
os_info.running_cluster = NULL;
}
On Fri, 2012-08-24 at 10:08 -0400, Tom Lane wrote:
Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
On 23.08.2012 23:07, Alvaro Herrera wrote:
One problem with this is that I get this warning:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c: In function ‘s_exec_prog’:
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]
/pgsql/source/HEAD/contrib/pg_upgrade/exec.c:96:2: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wmissing-format-attribute]I have no idea how to silence that. Ideas?
You can do what the warning suggests, and tell the compiler that
exec_prog takes printf-like arguments.exec_prog already has such decoration, and Alvaro's patch doesn't remove
it. So the question is, exactly what the heck does that warning mean?
The warning is about s_exec_prog, not exec_prog.
Excerpts from Alvaro Herrera's message of vie ago 24 11:44:33 -0400 2012:
Actually it seems better to just get rid of the extra varargs function
and just have a single exec_prog. The extra NULL argument is not
troublesome enough, it seems. Updated version attached.
Applied (with some very minor changes).
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
On 08/24/2012 11:44 AM, Alvaro Herrera wrote:
Again, win32 testing would be welcome. Sadly, buildfarm does not run
pg_upgrade's "make check".
Yesterday I added a new module to the buildfarm client code to run this
(<https://github.com/PGBuildFarm/client-code/commit/ab812cb9920c65e39ec7358dc816371f1fef31eb>).
It required a couple of tweaks in the base code. This will be in a new
buildfarm client release fairly shortly. It's running on crake now, and
I will add it to pitta to get some Windows coverage.
It would be a lot nicer is the test were written in Perl, since we don't
necessarily have a Bourne shell available for MSVC builds, but we
definitely have Perl available.
None of this does what I think we really need, which is cross-release
pg_upgrade testing, which remains on my TODO list as a fairly high
priority item.
cheers
andrew
On 08/31/2012 10:52 AM, Andrew Dunstan wrote:
On 08/24/2012 11:44 AM, Alvaro Herrera wrote:
Again, win32 testing would be welcome. Sadly, buildfarm does not run
pg_upgrade's "make check".Yesterday I added a new module to the buildfarm client code to run
this
(<https://github.com/PGBuildFarm/client-code/commit/ab812cb9920c65e39ec7358dc816371f1fef31eb>).
It required a couple of tweaks in the base code. This will be in a new
buildfarm client release fairly shortly. It's running on crake now,
and I will add it to pitta to get some Windows coverage.
but it's not working on pitta :-(
It will take me some time to work out why, and I have several more
urgent things on my plate. Meanwhile at least we have Linux coverage.
cheers
andrew