diff --git a/fabfile/pg_report_vg_query.patch b/fabfile/pg_report_vg_query.patch index e0fb35ab..e297d7ea 100644 --- a/fabfile/pg_report_vg_query.patch +++ b/fabfile/pg_report_vg_query.patch @@ -1,39 +1,168 @@ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c -index 470b734e9e..0798dff410 100644 +index 2fc49e3445..82bd080826 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c -@@ -73,6 +73,9 @@ - #include "utils/snapmgr.h" - #include "utils/timeout.h" - #include "utils/timestamp.h" +@@ -36,6 +36,10 @@ + #include "rusagestub.h" + #endif + +#ifdef USE_VALGRIND +#include +#endif ++ + #include "access/parallel.h" + #include "access/printtup.h" + #include "access/xact.h" +@@ -206,6 +210,36 @@ static void enable_statement_timeout(void); + static void disable_statement_timeout(void); - /* ---------------- - * global variables -@@ -986,6 +989,7 @@ exec_simple_query(const char *query_string) - bool was_logged = false; - bool use_implicit_block; - char msec_str[32]; -+ static long long unsigned vgErrorsSoFar = 0; - /* - * Report query to various monitoring facilities. -@@ -1343,6 +1347,16 @@ exec_simple_query(const char *query_string) - TRACE_POSTGRESQL_QUERY_DONE(query_string); ++/* ---------------------------------------------------------------- ++ * infrastructure for valgrind debugging ++ * ---------------------------------------------------------------- ++ */ ++#ifdef USE_VALGRIND ++/* This variable should be set at the top of the main loop. */ ++static unsigned int old_valgrind_error_count; ++ ++/* ++ * If Valgrind detected any errors since old_valgrind_error_count was updated, ++ * report the current query as the cause. This should be called at the end ++ * of message processing. ++ */ ++static void ++valgrind_report_error_query(const char *query) ++{ ++ unsigned int valgrind_error_count = VALGRIND_COUNT_ERRORS; ++ ++ if (unlikely(valgrind_error_count != old_valgrind_error_count) && ++ query != NULL) ++ VALGRIND_PRINTF("Valgrind detected %u error(s) during execution of \"%s\"\n", ++ valgrind_error_count - old_valgrind_error_count, ++ query); ++} ++ ++#else /* !USE_VALGRIND */ ++#define valgrind_report_error_query(query) ((void) 0) ++#endif /* USE_VALGRIND */ ++ ++ + /* ---------------------------------------------------------------- + * routines to obtain user input + * ---------------------------------------------------------------- +@@ -2052,6 +2086,8 @@ exec_bind_message(StringInfo input_message) + if (save_log_statement_stats) + ShowUsage("BIND MESSAGE STATISTICS"); ++ valgrind_report_error_query(debug_query_string); ++ debug_query_string = NULL; + } + +@@ -2299,6 +2335,8 @@ exec_execute_message(const char *portal_name, long max_rows) + if (save_log_statement_stats) + ShowUsage("EXECUTE MESSAGE STATISTICS"); + ++ valgrind_report_error_query(debug_query_string); + + debug_query_string = NULL; + } + +@@ -4308,6 +4346,12 @@ PostgresMain(const char *dbname, const char *username) + /* Report the error to the client and/or server log */ + EmitErrorReport(); + ++ /* ++ * If Valgrind noticed something during the erroneous query, print the ++ * query string, assuming we have one. ++ */ ++ valgrind_report_error_query(debug_query_string); ++ + /* + * Make sure debug_query_string gets reset before we possibly clobber + * the storage it points at. +@@ -4392,6 +4436,13 @@ PostgresMain(const char *dbname, const char *username) + */ + doing_extended_query_message = false; + ++ /* ++ * For valgrind reporting purposes, the "current query" begins here. ++ */ +#ifdef USE_VALGRIND -+ if (VALGRIND_COUNT_ERRORS > vgErrorsSoFar) -+ { -+ VALGRIND_PRINTF("The query for which valgrind reported a " -+ "memory error was: %s\n", -+ query_string); -+ } -+ vgErrorsSoFar = VALGRIND_COUNT_ERRORS; ++ old_valgrind_error_count = VALGRIND_COUNT_ERRORS; +#endif - } ++ + /* + * Release storage left over from prior query cycle, and create a new + * query input buffer in the cleared MessageContext. +@@ -4592,6 +4643,8 @@ PostgresMain(const char *dbname, const char *username) + else + exec_simple_query(query_string); + ++ valgrind_report_error_query(query_string); ++ + send_ready_for_query = true; + } + break; +@@ -4621,6 +4674,8 @@ PostgresMain(const char *dbname, const char *username) + + exec_parse_message(query_string, stmt_name, + paramTypes, numParams); ++ ++ valgrind_report_error_query(query_string); + } + break; + +@@ -4635,6 +4690,8 @@ PostgresMain(const char *dbname, const char *username) + * the field extraction out-of-line + */ + exec_bind_message(&input_message); ++ ++ /* exec_bind_message does valgrind_report_error_query */ + break; + + case 'E': /* execute */ +@@ -4652,6 +4709,8 @@ PostgresMain(const char *dbname, const char *username) + pq_getmsgend(&input_message); + + exec_execute_message(portal_name, max_rows); ++ ++ /* exec_execute_message does valgrind_report_error_query */ + } + break; + +@@ -4685,6 +4744,8 @@ PostgresMain(const char *dbname, const char *username) + /* commit the function-invocation transaction */ + finish_xact_command(); + ++ valgrind_report_error_query("fastpath function call"); ++ + send_ready_for_query = true; + break; + +@@ -4729,6 +4790,8 @@ PostgresMain(const char *dbname, const char *username) + + if (whereToSendOutput == DestRemote) + pq_putemptymessage('3'); /* CloseComplete */ ++ ++ valgrind_report_error_query("CLOSE message"); + } + break; + +@@ -4761,6 +4824,8 @@ PostgresMain(const char *dbname, const char *username) + describe_type))); + break; + } ++ ++ valgrind_report_error_query("DESCRIBE message"); + } + break; + +@@ -4773,6 +4838,7 @@ PostgresMain(const char *dbname, const char *username) + case 'S': /* sync */ + pq_getmsgend(&input_message); + finish_xact_command(); ++ valgrind_report_error_query("SYNC message"); + send_ready_for_query = true; + break; - /*