From: Philippe Waroquiers Date: Mon, 12 Aug 2013 22:17:47 +0000 (+0000) Subject: kludge to bypass inner valgrind mmap failing due to not observed outer mmap X-Git-Tag: svn/VALGRIND_3_9_0~196 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4d8ec8f74a074fa3020f8702927635d51e5cd44e;p=thirdparty%2Fvalgrind.git kludge to bypass inner valgrind mmap failing due to not observed outer mmap Some tests are failing in an "outer/inner" setup with an "out of memory" situation reported by the inner (e.g. memcheck/tests/err_disable4.vgtest). Looks like this is because the inner valgrind aspacemgr believes a segment is free and can be used, but segment is in fact used by the outer. This can happen as the inner cannot observe the outer mmap, and so inner aspacemgr can be out of sync with the kernel and the outer. This kludge bypasses the problem: if the fixed mmap fails in the inner, the inner retries without the fixed. This is a kludge as the proper solution would be to have a correct state of aspacemgr in the inner. This however implies a more in-depth surgery in the outer/inner setup (to have e.g. the outer informing the inner of its own mmap or alternatively having the inner asking the outer about the mmap advisory). Kludge is preferred (at least now) as this kludge is activated only for the inner (and for darwin, but that was already like that). Of course, this kludge does not the state of the inner aspacemgr matching the outer and kernel state. So, other problems might be detected e.g. if inner aspacemgr does a check comparing its status with kernel status. The patch also ensures the inner reports the memory status of the outer (using a client request) when an out of memory situation is detected. This helps understanding what goes wrong. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13495 --- diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c index 9db3820a23..970979300f 100644 --- a/coregrind/m_aspacemgr/aspacemgr-linux.c +++ b/coregrind/m_aspacemgr/aspacemgr-linux.c @@ -2448,14 +2448,27 @@ SysRes VG_(am_mmap_anon_float_valgrind)( SizeT length ) another thread can pre-empt our spot. [At one point on the DARWIN branch the VKI_MAP_FIXED was commented out; unclear if this is necessary or not given the second Darwin-only call that immediately - follows if this one fails. --njn] */ + follows if this one fails. --njn] + Also, an inner valgrind cannot observe the mmap syscalls done by + the outer valgrind. The outer Valgrind might make the mmap + fail here, as the inner valgrind believes that a segment is free, + while it is in fact used by the outer valgrind. + So, for an inner valgrind, similarly to DARWIN, if the fixed mmap + fails, retry the mmap without map fixed. + This is a kludge which on linux is only activated for the inner. + The state of the inner aspacemgr is not made correct by this kludge + and so a.o. VG_(am_do_sync_check) could fail. + A proper solution implies a better collaboration between the + inner and the outer (e.g. inner VG_(am_get_advisory) should do + a client request to call the outer VG_(am_get_advisory). */ sres = VG_(am_do_mmap_NO_NOTIFY)( advised, length, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, VM_TAG_VALGRIND, 0 ); -#if defined(VGO_darwin) +#if defined(VGO_darwin) || defined(ENABLE_INNER) + /* Kludge on Darwin and inner linux if the fixed mmap failed. */ if (sr_isError(sres)) { /* try again, ignoring the advisory */ sres = VG_(am_do_mmap_NO_NOTIFY)( @@ -2469,7 +2482,9 @@ SysRes VG_(am_mmap_anon_float_valgrind)( SizeT length ) if (sr_isError(sres)) return sres; -#if defined(VGO_linux) +#if defined(VGO_linux) && !defined(ENABLE_INNER) + /* Doing the check only in linux not inner, as the below + check can fail when the kludge above has been used. */ if (sr_Res(sres) != advised) { /* I don't think this can happen. It means the kernel made a fixed map succeed but not at the requested location. Try to diff --git a/coregrind/m_mallocfree.c b/coregrind/m_mallocfree.c index 16bc81d536..d9e10e25ff 100644 --- a/coregrind/m_mallocfree.c +++ b/coregrind/m_mallocfree.c @@ -762,6 +762,10 @@ void VG_(out_of_memory_NORETURN) ( const HChar* who, SizeT szB ) VG_(print_all_arena_stats) (); if (VG_(clo_profile_heap)) VG_(print_arena_cc_analysis) (); + /* In case we are an inner valgrind, asks the outer to report + its memory state in its log output. */ + INNER_REQUEST(VALGRIND_MONITOR_COMMAND("v.set log_output")); + INNER_REQUEST(VALGRIND_MONITOR_COMMAND("v.info memory aspacemgr")); } outputTrial++; VG_(message)(Vg_UserMsg, s1, who, (ULong)szB, tot_alloc);