diff options
author | Marc Alff <marc.alff@oracle.com> | 2012-03-28 17:54:30 +0200 |
---|---|---|
committer | Marc Alff <marc.alff@oracle.com> | 2012-03-28 17:54:30 +0200 |
commit | 7553f9eefdcdf67d31caa2a64b826dd476b4c35e (patch) | |
tree | 7618c8a84b83e005ba904405ff83842efaf9db67 /storage | |
parent | fe12e0b2cc2230f6509783d34afeb5069aaf0034 (diff) | |
download | mariadb-git-7553f9eefdcdf67d31caa2a64b826dd476b4c35e.tar.gz |
Bug#13898343 THREAD LOOPS ENDLESSLY IN LF_PINBOX_PUT_PINS WHILE HOLDING
LOCK_THREAD_COUNT
When using the performance schema file io instrumentation in MySQL 5.5,
a thread would loop forever inside lf_pinbox_put_pins, when disconnecting.
It would also hold LOCK_thread_count while doing so, effectively killing the
server.
The root cause of the loop in lf_pinbox_put_pins() is a leak of LF_PINS,
when used with the filename_hash LF_HASH table in the performance schema.
This fix contains the following changes:
1)
Added the missing call to lf_hash_search_unpin(), to prevent the leak.
2)
In mysys/lf_alloc-pin.c, there was some extra debugging code
(MY_LF_EXTRA_DEBUG) written to detect precisely this kind of issues,
but it was never used.
Replaced MY_LF_EXTRA_DEBUG with DBUG_OFF, so that leaks similar to this one
can be always detected in regular debug builds.
3)
Backported the fix for the following bug, from 5.6 to 5.5:
Bug#13417446 - 63339: INCORRECT FILE PATH IN PEFORMANCE_SCHEMA ON WINDOWS
Diffstat (limited to 'storage')
-rw-r--r-- | storage/perfschema/pfs_instr.cc | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index a877ea61198..c83628cb7cd 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -802,6 +802,22 @@ void destroy_thread(PFS_thread *pfs) } /** + Get the hash pins for @filename_hash. + @param thread The running thread. + @returns The LF_HASH pins for the thread. +*/ +LF_PINS* get_filename_hash_pins(PFS_thread *thread) +{ + if (unlikely(thread->m_filename_hash_pins == NULL)) + { + if (! filename_hash_inited) + return NULL; + thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash); + } + return thread->m_filename_hash_pins; +} + +/** Find or create instrumentation for a file instance by file name. @param thread the executing instrumented thread @param klass the file class @@ -816,23 +832,13 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, PFS_file *pfs; PFS_scan scan; - if (! filename_hash_inited) + LF_PINS *pins= get_filename_hash_pins(thread); + if (unlikely(pins == NULL)) { - /* File instrumentation can be turned off. */ file_lost++; return NULL; } - if (unlikely(thread->m_filename_hash_pins == NULL)) - { - thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash); - if (unlikely(thread->m_filename_hash_pins == NULL)) - { - file_lost++; - return NULL; - } - } - char safe_buffer[FN_REFLEN]; const char *safe_filename; @@ -904,7 +910,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, /* Append the unresolved file name to the resolved path */ char *ptr= buffer + strlen(buffer); char *buf_end= &buffer[sizeof(buffer)-1]; - if (buf_end > ptr) + if ((buf_end > ptr) && (*(ptr-1) != FN_LIBCHAR)) *ptr++= FN_LIBCHAR; if (buf_end > ptr) strncpy(ptr, safe_filename + dirlen, buf_end - ptr); @@ -918,16 +924,18 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, const uint retry_max= 3; search: entry= reinterpret_cast<PFS_file**> - (lf_hash_search(&filename_hash, thread->m_filename_hash_pins, + (lf_hash_search(&filename_hash, pins, normalized_filename, normalized_length)); if (entry && (entry != MY_ERRPTR)) { pfs= *entry; pfs->m_file_stat.m_open_count++; - lf_hash_search_unpin(thread->m_filename_hash_pins); + lf_hash_search_unpin(pins); return pfs; } + lf_hash_search_unpin(pins); + /* filename is not constant, just using it for noise on create */ uint random= randomized_index(filename, file_max); @@ -954,7 +962,7 @@ search: reset_single_stat_link(&pfs->m_wait_stat); int res; - res= lf_hash_insert(&filename_hash, thread->m_filename_hash_pins, + res= lf_hash_insert(&filename_hash, pins, &pfs); if (likely(res == 0)) { @@ -1006,9 +1014,12 @@ void release_file(PFS_file *pfs) void destroy_file(PFS_thread *thread, PFS_file *pfs) { DBUG_ASSERT(thread != NULL); - DBUG_ASSERT(thread->m_filename_hash_pins != NULL); DBUG_ASSERT(pfs != NULL); - lf_hash_delete(&filename_hash, thread->m_filename_hash_pins, + + LF_PINS *pins= get_filename_hash_pins(thread); + DBUG_ASSERT(pins != NULL); + + lf_hash_delete(&filename_hash, pins, pfs->m_filename, pfs->m_filename_length); pfs->m_lock.allocated_to_free(); } |