From: Julian Seward Date: Sat, 5 Oct 2002 14:15:43 +0000 (+0000) Subject: Implement, and document, the --run-libc-freeres=no|yes flag. X-Git-Tag: svn/VALGRIND_1_9_4~241 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b2ec9dae1b4b1eee2d54a7aab5fe2f3d60788249;p=thirdparty%2Fvalgrind.git Implement, and document, the --run-libc-freeres=no|yes flag. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1186 --- diff --git a/coregrind/docs/manual.html b/coregrind/docs/manual.html index 0fad606fa0..39e4227633 100644 --- a/coregrind/docs/manual.html +++ b/coregrind/docs/manual.html @@ -585,6 +585,33 @@ follows: in g++-3.0.4.

+

  • --run-libc-freeres=yes [the default]
    + --run-libc-freeres=no +

    The GNU C library (libc.so), which is used by + all programs, may allocate memory for its own uses. Usually it + doesn't bother to free that memory when the program ends - there + would be no point, since the Linux kernel reclaims all process + resources when a process exits anyway, so it would just slow + things down. +

    + The glibc authors realised that this behaviour causes leak checkers, such + as Valgrind, to falsely report leaks in glibc, when a leak check + is done at exit. In order to avoid this, they provided a + routine called __libc_freeres specifically to make + glibc release all memory it has allocated. The MemCheck and + AddrCheck skins (normal and lightweight valgrinding) therefore + try and run __libc_freeres at exit. +

    + Unfortunately, in some versions of glibc, + __libc_freeres is sufficiently buggy to cause + segmentation faults. This is particularly noticeable on Red Hat + 7.1. So this flag is provided in order to inhibit the run of + __libc_freeres. If your program seems to run fine + on valgrind, but segfaults at exit, you may find that + --run-libc-freeres=no fixes that, although at the + cost of possibly falsely reporting space leaks in + libc.so. +

  • --error-limit=yes [default]
    --error-limit=no

    When enabled, valgrind stops reporting errors after 30000 in total, or 300 different ones, @@ -592,12 +619,6 @@ follows: from becoming a huge performance overhead in programs with many errors.


  • -

  • --cachesim=no [default]
    - --cachesim=yes

    When enabled, turns off memory - checking, and turns on cache profiling. Cache profiling is - described in detail in Section 7. -


  • -

  • --weird-hacks=hack1,hack2,... Pass miscellaneous hints to Valgrind which slightly modify the simulated behaviour in nonstandard or dangerous ways, possibly diff --git a/coregrind/vg_clientfuncs.c b/coregrind/vg_clientfuncs.c index 689881869f..49edc0fc37 100644 --- a/coregrind/vg_clientfuncs.c +++ b/coregrind/vg_clientfuncs.c @@ -584,7 +584,7 @@ void VG_(__libc_freeres_wrapper)( void ) { int res; extern void __libc_freeres(void); - //__libc_freeres(); + __libc_freeres(); VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */, VG_USERREQ__LIBC_FREERES_DONE, 0, 0, 0, 0); /*NOTREACHED*/ diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index ed2fe5786a..164e896610 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -204,6 +204,12 @@ extern Int VG_(clo_dump_error); extern Int VG_(clo_backtrace_size); /* Engage miscellaneous wierd hacks needed for some progs. */ extern Char* VG_(clo_weird_hacks); +/* Should we run __libc_freeres at exit? Sometimes causes crashes. + Default: YES. Note this is subservient to VG_(needs).libc_freeres; + if the latter says False, then the setting of VG_(clo_weird_hacks) + is ignored. Ie if a skin says no, I don't want this to run, that + cannot be overridden from the command line. */ +extern Bool VG_(clo_run_libc_freeres); /* --------------------------------------------------------------------- diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index cb5891ed14..c51fb2a22c 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -550,6 +550,7 @@ ULong VG_(clo_stop_after) = 1000000000000LL; Int VG_(clo_dump_error) = 0; Int VG_(clo_backtrace_size) = 4; Char* VG_(clo_weird_hacks) = NULL; +Bool VG_(clo_run_libc_freeres) = True; /* This Bool is needed by wrappers in vg_clientmalloc.c to decide how to behave. Initially we say False. */ @@ -618,6 +619,7 @@ static void usage ( void ) " --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n" " --alignment= set minimum alignment of allocations [4]\n" " --trace-children=no|yes Valgrind-ise child processes? [no]\n" +" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n" " --logfile-fd= file descriptor for messages [2=stderr]\n" " --suppressions= suppress errors described in\n" " suppressions file \n" @@ -869,6 +871,11 @@ static void process_cmd_line_options ( void ) else if (STREQ(argv[i], "--trace-children=no")) VG_(clo_trace_children) = False; + else if (STREQ(argv[i], "--run-libc-freeres=yes")) + VG_(clo_run_libc_freeres) = True; + else if (STREQ(argv[i], "--run-libc-freeres=no")) + VG_(clo_run_libc_freeres) = False; + else if (STREQN(15, argv[i], "--sanity-level=")) VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]); diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 4dbd4c97b8..a10165dbc1 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -1479,31 +1479,42 @@ VgSchedReturnCode VG_(scheduler) ( void ) __libc_freeres does some invalid frees which crash the unprotected malloc/free system. */ - /* If __NR_exit, remember the supplied argument. */ - if (VG_(threads)[tid].m_eax == __NR_exit) + if (VG_(threads)[tid].m_eax == __NR_exit) { + + /* If __NR_exit, remember the supplied argument. */ VG_(exitcode) = VG_(threads)[tid].m_ebx; /* syscall arg1 */ - if (VG_(threads)[tid].m_eax == __NR_exit - && ! VG_(needs).libc_freeres) { - if (VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) { - VG_(message)(Vg_DebugMsg, - "Caught __NR_exit; quitting"); - } - return VgSrc_ExitSyscall; - } + /* Only run __libc_freeres if the skin says it's ok and + it hasn't been overridden with --run-libc-freeres=no + on the command line. */ + + if (VG_(needs).libc_freeres && VG_(clo_run_libc_freeres)) { + + if (VG_(clo_verbosity) >= 2 + || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) { + VG_(message)(Vg_DebugMsg, + "Caught __NR_exit; running __libc_freeres()"); + } + VG_(nuke_all_threads_except) ( tid ); + VG_(threads)[tid].m_eip = (UInt)(&VG_(__libc_freeres_wrapper)); + vg_assert(VG_(threads)[tid].status == VgTs_Runnable); + goto stage1; /* party on, dudes (but not for much longer :) */ + + } else { + /* We won't run __libc_freeres; just exit now. */ + if (VG_(clo_verbosity) >= 2 + || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) { + VG_(message)(Vg_DebugMsg, + "Caught __NR_exit; quitting"); + } + return VgSrc_ExitSyscall; + } - if (VG_(threads)[tid].m_eax == __NR_exit) { - vg_assert(VG_(needs).libc_freeres); - if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) { - VG_(message)(Vg_DebugMsg, - "Caught __NR_exit; running __libc_freeres()"); - } - VG_(nuke_all_threads_except) ( tid ); - VG_(threads)[tid].m_eip = (UInt)(&VG_(__libc_freeres_wrapper)); - vg_assert(VG_(threads)[tid].status == VgTs_Runnable); - goto stage1; /* party on, dudes (but not for much longer :) */ } + /* We've dealt with __NR_exit at this point. */ + vg_assert(VG_(threads)[tid].m_eax != __NR_exit); + /* Trap syscalls to __NR_sched_yield and just have this thread yield instead. Not essential, just an optimisation. */