@ -27,6 +27,10 @@
# include <sys/socket.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <sys/time.h>
# ifdef USE_VALGRIND
# include <valgrind/valgrind.h>
# endif
# include "access/parallel.h"
# include "access/parallel.h"
# include "access/printtup.h"
# include "access/printtup.h"
# include "access/xact.h"
# include "access/xact.h"
@ -191,6 +195,36 @@ static void enable_statement_timeout(void);
static void disable_statement_timeout ( void ) ;
static void disable_statement_timeout ( void ) ;
/* ----------------------------------------------------------------
* 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
* routines to obtain user input
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -2041,6 +2075,8 @@ exec_bind_message(StringInfo input_message)
if ( save_log_statement_stats )
if ( save_log_statement_stats )
ShowUsage ( " BIND MESSAGE STATISTICS " ) ;
ShowUsage ( " BIND MESSAGE STATISTICS " ) ;
valgrind_report_error_query ( debug_query_string ) ;
debug_query_string = NULL ;
debug_query_string = NULL ;
}
}
@ -2292,6 +2328,8 @@ exec_execute_message(const char *portal_name, long max_rows)
if ( save_log_statement_stats )
if ( save_log_statement_stats )
ShowUsage ( " EXECUTE MESSAGE STATISTICS " ) ;
ShowUsage ( " EXECUTE MESSAGE STATISTICS " ) ;
valgrind_report_error_query ( debug_query_string ) ;
debug_query_string = NULL ;
debug_query_string = NULL ;
}
}
@ -4287,6 +4325,12 @@ PostgresMain(const char *dbname, const char *username)
/* Report the error to the client and/or server log */
/* Report the error to the client and/or server log */
EmitErrorReport ( ) ;
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
* Make sure debug_query_string gets reset before we possibly clobber
* the storage it points at .
* the storage it points at .
@ -4371,6 +4415,13 @@ PostgresMain(const char *dbname, const char *username)
*/
*/
doing_extended_query_message = false ;
doing_extended_query_message = false ;
/*
* For valgrind reporting purposes , the " current query " begins here .
*/
# ifdef USE_VALGRIND
old_valgrind_error_count = VALGRIND_COUNT_ERRORS ;
# endif
/*
/*
* Release storage left over from prior query cycle , and create a new
* Release storage left over from prior query cycle , and create a new
* query input buffer in the cleared MessageContext .
* query input buffer in the cleared MessageContext .
@ -4571,6 +4622,8 @@ PostgresMain(const char *dbname, const char *username)
else
else
exec_simple_query ( query_string ) ;
exec_simple_query ( query_string ) ;
valgrind_report_error_query ( query_string ) ;
send_ready_for_query = true ;
send_ready_for_query = true ;
}
}
break ;
break ;
@ -4600,6 +4653,8 @@ PostgresMain(const char *dbname, const char *username)
exec_parse_message ( query_string , stmt_name ,
exec_parse_message ( query_string , stmt_name ,
paramTypes , numParams ) ;
paramTypes , numParams ) ;
valgrind_report_error_query ( query_string ) ;
}
}
break ;
break ;
@ -4614,6 +4669,8 @@ PostgresMain(const char *dbname, const char *username)
* the field extraction out - of - line
* the field extraction out - of - line
*/
*/
exec_bind_message ( & input_message ) ;
exec_bind_message ( & input_message ) ;
/* exec_bind_message does valgrind_report_error_query */
break ;
break ;
case ' E ' : /* execute */
case ' E ' : /* execute */
@ -4631,6 +4688,8 @@ PostgresMain(const char *dbname, const char *username)
pq_getmsgend ( & input_message ) ;
pq_getmsgend ( & input_message ) ;
exec_execute_message ( portal_name , max_rows ) ;
exec_execute_message ( portal_name , max_rows ) ;
/* exec_execute_message does valgrind_report_error_query */
}
}
break ;
break ;
@ -4664,6 +4723,8 @@ PostgresMain(const char *dbname, const char *username)
/* commit the function-invocation transaction */
/* commit the function-invocation transaction */
finish_xact_command ( ) ;
finish_xact_command ( ) ;
valgrind_report_error_query ( " fastpath function call " ) ;
send_ready_for_query = true ;
send_ready_for_query = true ;
break ;
break ;
@ -4708,6 +4769,8 @@ PostgresMain(const char *dbname, const char *username)
if ( whereToSendOutput = = DestRemote )
if ( whereToSendOutput = = DestRemote )
pq_putemptymessage ( ' 3 ' ) ; /* CloseComplete */
pq_putemptymessage ( ' 3 ' ) ; /* CloseComplete */
valgrind_report_error_query ( " CLOSE message " ) ;
}
}
break ;
break ;
@ -4740,6 +4803,8 @@ PostgresMain(const char *dbname, const char *username)
describe_type ) ) ) ;
describe_type ) ) ) ;
break ;
break ;
}
}
valgrind_report_error_query ( " DESCRIBE message " ) ;
}
}
break ;
break ;
@ -4752,6 +4817,7 @@ PostgresMain(const char *dbname, const char *username)
case ' S ' : /* sync */
case ' S ' : /* sync */
pq_getmsgend ( & input_message ) ;
pq_getmsgend ( & input_message ) ;
finish_xact_command ( ) ;
finish_xact_command ( ) ;
valgrind_report_error_query ( " SYNC message " ) ;
send_ready_for_query = true ;
send_ready_for_query = true ;
break ;
break ;