diff options
author | cmiller@zippy.cornsilk.net <> | 2007-04-06 09:15:18 -0400 |
---|---|---|
committer | cmiller@zippy.cornsilk.net <> | 2007-04-06 09:15:18 -0400 |
commit | 88455a047f7d542d3670c073b704cfa2848279d4 (patch) | |
tree | f80fd4f330f95124b1f5560ce915ec1765b8ec62 /sql/sql_profile.cc | |
parent | 6204ae25fc6d6b2153e0e9ab14eee0c0ce5a2e2a (diff) | |
download | mariadb-git-88455a047f7d542d3670c073b704cfa2848279d4.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.
Diffstat (limited to 'sql/sql_profile.cc')
-rw-r--r-- | sql/sql_profile.cc | 18 |
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(); |