summaryrefslogtreecommitdiff
path: root/sql/sql_profile.cc
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2007-04-06 09:15:18 -0400
committerunknown <cmiller@zippy.cornsilk.net>2007-04-06 09:15:18 -0400
commit36dfa68ca7b160d186bd69232a7622c78614f3ad (patch)
treef80fd4f330f95124b1f5560ce915ec1765b8ec62 /sql/sql_profile.cc
parent64ad08661934191b08b5dcbf36213bb1f7f59ec0 (diff)
downloadmariadb-git-36dfa68ca7b160d186bd69232a7622c78614f3ad.tar.gz
Changing the state of whether we're recording profiling information
halfway through a query (as happens in "SET SESSION PROFILING = ...") has a few side-effects, the worst of which is a memory leak for prepared statements, which poke directly from the parser into the profiling code (we don't have the query text when we need it) and that overwrites a pointer to heap-allocated memory when the previous statement turns on profiling. Instead, now set a flag when we begin a new statement that tracks whether profiling is on _at the start_ of the query. Use that to track whether we gather info. Additionally, use that AND use the state of the profiling variable after the end of a query to know whether to store information about the query that just finished. mysql-test/r/profiling.result: Testing whether profiling is on at the beginning of a query and at the end of a query makes "SET SESSION PROFILING = ..." statements disappear from the profiling. They were never reliable before. sql/sql_profile.cc: Check to see if profiling was enabled at the beginning of this query before trying to store query_source. This avoids a memory leak for prepared statements, which get here by direct means. If profiling was toggled in this query, then don't store this query profile. sql/sql_profile.h: Keep track of whether profiling is on.
Diffstat (limited to 'sql/sql_profile.cc')
-rw-r--r--sql/sql_profile.cc18
1 files changed, 15 insertions, 3 deletions
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index 5fd83ce70c6..91b0b062e4f 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -168,10 +168,14 @@ QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg,
void QUERY_PROFILE::set_query_source(char *query_source_arg,
uint query_length_arg)
{
+ if (! profiling->enabled)
+ return;
+
/* Truncate to avoid DoS attacks. */
uint length= min(MAX_QUERY_LENGTH, query_length_arg);
/* TODO?: Provide a way to include the full text, as in SHOW PROCESSLIST. */
+ DBUG_ASSERT(query_source == NULL);
if (query_source_arg != NULL)
query_source= my_strdup_with_length(query_source_arg, length, MYF(0));
}
@@ -445,7 +449,7 @@ bool QUERY_PROFILE::show(uint options)
}
PROFILING::PROFILING()
- :profile_id_counter(1), keeping(1), current(NULL), last(NULL)
+ :profile_id_counter(1), keeping(TRUE), enabled(FALSE), current(NULL), last(NULL)
{
}
@@ -464,7 +468,7 @@ void PROFILING::status_change(const char *status_arg,
{
DBUG_ENTER("PROFILING::status_change");
- if (unlikely((thd->options & OPTION_PROFILING) != 0))
+ if (unlikely(enabled))
{
if (unlikely(current == NULL))
reset();
@@ -499,6 +503,8 @@ void PROFILING::store()
if (current != NULL)
{
if (keeping &&
+ (enabled) && /* ON at start? */
+ (((thd)->options & OPTION_PROFILING) != 0) && /* and ON at end? */
(current->query_source != NULL) &&
(current->query_source[0] != '\0') &&
(!current->entries.is_empty()))
@@ -517,7 +523,8 @@ void PROFILING::store()
}
DBUG_ASSERT(current == NULL);
- current= new QUERY_PROFILE(this, thd->query, thd->query_length);
+ if (enabled)
+ current= new QUERY_PROFILE(this, thd->query, thd->query_length);
DBUG_VOID_RETURN;
}
@@ -534,7 +541,12 @@ void PROFILING::reset()
store();
if (likely(((thd)->options & OPTION_PROFILING) == 0))
+ {
+ enabled= FALSE;
DBUG_VOID_RETURN;
+ }
+ else
+ enabled= TRUE;
if (current != NULL)
current->reset();