From patchwork Fri Aug 8 19:46:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kwok Cheung Yeung X-Patchwork-Id: 2354 Received: (qmail 30775 invoked by alias); 8 Aug 2014 19:46:34 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 30762 invoked by uid 89); 8 Aug 2014 19:46:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00 autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Message-ID: <53E5290E.1000907@codesourcery.com> Date: Fri, 8 Aug 2014 20:46:22 +0100 From: Kwok Cheung Yeung User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 MIME-Version: 1.0 To: CC: Joseph Myers , Andrew Stubbs Subject: [PATCH][BZ #16573] Fix for hang when using mtrace with MALLOC_TRACE set A hang can occur if the mtrace output is diverted to a file (by setting the MALLOC_TRACE environment variable) and an mtrace problem is found. The mtrace hook leads to a call of __libc_message(), which eventually results in a call to malloc(), causing another mtrace hook to be called. This hook then attempts to reacquire the same lock that was already claimed by the first hook, resulting in an infinite hang. This patch fixes this by making all mtrace hooks temporarily uninstall all mtrace hooks for the duration of the call, so that there will not be another call to an mtrace hook further down the call chain. Kwok 2014-08-08 Kwok Cheung Yeung [BZ #16573] * malloc/mtrace.c (tr_freehook): Move function prototype to before the hook definitions. Disable all hooks before calling the caller or old hook, and re-enable all hooks afterwards. (tr_mallochook): Likewise. (tr_reallochook): Likewise. (tr_freehook): Likewise. --- else @@ -194,6 +211,7 @@ tr_reallochook (__ptr_t ptr, size_t size, const __ptr_t caller) __free_hook = tr_freehook; __malloc_hook = tr_mallochook; __realloc_hook = tr_reallochook; + __memalign_hook = tr_memalignhook; tr_where (caller, info); if (hdr == NULL) @@ -229,14 +247,18 @@ tr_memalignhook (size_t alignment, size_t size, const __ptr_t caller) Dl_info mem; Dl_info *info = lock_and_info (caller, &mem); - __memalign_hook = tr_old_memalign_hook; + __free_hook = tr_old_free_hook; __malloc_hook = tr_old_malloc_hook; + __realloc_hook = tr_old_realloc_hook; + __memalign_hook = tr_old_memalign_hook; if (tr_old_memalign_hook != NULL) hdr = (__ptr_t) (*tr_old_memalign_hook)(alignment, size, caller); else hdr = (__ptr_t) memalign (alignment, size); - __memalign_hook = tr_memalignhook; + __free_hook = tr_freehook; __malloc_hook = tr_mallochook; + __realloc_hook = tr_reallochook; + __memalign_hook = tr_memalignhook; tr_where (caller, info); /* We could be printing a NULL here; that's OK. */ diff --git a/malloc/mtrace.c b/malloc/mtrace.c index 91e5710..593b212 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -120,6 +120,10 @@ lock_and_info (const __ptr_t caller, Dl_info *mem) return res; } +static __ptr_t tr_mallochook (size_t, const __ptr_t); +static __ptr_t tr_reallochook (__ptr_t, size_t, const __ptr_t); +static __ptr_t tr_memalignhook (size_t, size_t, const __ptr_t); + static void tr_freehook (__ptr_t ptr, const __ptr_t caller) { @@ -138,11 +142,17 @@ tr_freehook (__ptr_t ptr, const __ptr_t caller) __libc_lock_lock (lock); } __free_hook = tr_old_free_hook; + __malloc_hook = tr_old_malloc_hook; + __realloc_hook = tr_old_realloc_hook; + __memalign_hook = tr_old_memalign_hook; if (tr_old_free_hook != NULL) (*tr_old_free_hook)(ptr, caller); else free (ptr); __free_hook = tr_freehook; + __malloc_hook = tr_mallochook; + __realloc_hook = tr_reallochook; + __memalign_hook = tr_memalignhook; __libc_lock_unlock (lock); } @@ -154,12 +164,18 @@ tr_mallochook (size_t size, const __ptr_t caller) Dl_info mem; Dl_info *info = lock_and_info (caller, &mem); + __free_hook = tr_old_free_hook; __malloc_hook = tr_old_malloc_hook; + __realloc_hook = tr_old_realloc_hook; + __memalign_hook = tr_old_memalign_hook; if (tr_old_malloc_hook != NULL) hdr = (__ptr_t) (*tr_old_malloc_hook)(size, caller); else hdr = (__ptr_t) malloc (size); + __free_hook = tr_freehook; __malloc_hook = tr_mallochook; + __realloc_hook = tr_reallochook; + __memalign_hook = tr_memalignhook; tr_where (caller, info); /* We could be printing a NULL here; that's OK. */ @@ -187,6 +203,7 @@ tr_reallochook (__ptr_t ptr, size_t size, const __ptr_t caller) __free_hook = tr_old_free_hook; __malloc_hook = tr_old_malloc_hook; __realloc_hook = tr_old_realloc_hook; + __memalign_hook = tr_old_memalign_hook; if (tr_old_realloc_hook != NULL) hdr = (__ptr_t) (*tr_old_realloc_hook)(ptr, size, caller);