]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
At request of Ulrich Drepper, call __libc_freeres() after final __NR_exit
authorJulian Seward <jseward@acm.org>
Tue, 16 Jul 2002 01:43:15 +0000 (01:43 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 16 Jul 2002 01:43:15 +0000 (01:43 +0000)
so as to free memory allocated by glibc.  This reduces the leaks reported
in glibc, but causes a stack of read/write-after-free errors which have
to be suppressed :-(

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@507

coregrind/vg_clientfuncs.c
coregrind/vg_include.h
coregrind/vg_scheduler.c
glibc-2.2.supp
vg_clientfuncs.c
vg_include.h
vg_scheduler.c

index 9e498e0518f39a49ca1023bf4824411de0dc810f..80bdae67149915bebef4be2484bedf01b4d9d53c 100644 (file)
@@ -552,6 +552,23 @@ int sigsuspend ( /* const sigset_t * */ void* mask)
    return -1;
 }
 
+
+/* ---------------------------------------------------------------------
+   Hook for running __libc_freeres once the program exits.
+   ------------------------------------------------------------------ */
+
+void VG_(__libc_freeres_wrapper)( void )
+{
+   int res;
+   extern void __libc_freeres(void);
+   __libc_freeres();
+   VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
+                           VG_USERREQ__LIBC_FREERES_DONE, 0, 0, 0, 0);
+   /*NOTREACHED*/
+   vg_assert(12345+54321 == 999999);
+}
+
+
 /*--------------------------------------------------------------------*/
 /*--- end                                         vg_clientfuncs.c ---*/
 /*--------------------------------------------------------------------*/
index 31ba8e92158e87313a3e50a4592b1936e4210ecb..0d38c92332e4b868f90b24cf6c80a275cdd44010 100644 (file)
@@ -519,6 +519,9 @@ extern Bool  VG_(is_empty_arena) ( ArenaId aid );
 #define VG_USERREQ__SET_FHSTACK_ENTRY       0x3027
 #define VG_USERREQ__GET_FHSTACK_ENTRY       0x3028
 
+/* Denote the finish of VG_(__libc_freeres_wrapper). */
+#define VG_USERREQ__LIBC_FREERES_DONE       0x3029
+
 /* Cosmetic ... */
 #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101
 /* Log a pthread error from client-space.  Cosmetic. */
@@ -529,6 +532,10 @@ In vg_constants.h:
 #define VG_USERREQ__SIGNAL_RETURNS          0x4001
 */
 
+/* The scheduler does need to know the address of it so it can be
+   called at program exit. */
+extern void VG_(__libc_freeres_wrapper)( void );
+
 
 /* ---------------------------------------------------------------------
    Constants pertaining to the simulated CPU state, VG_(baseBlock),
index 823c85908deee18865c738a625150e36dd3a1fbd..43b018917acac06b3044afd54c63d9dc14ebf4f5 100644 (file)
@@ -1337,6 +1337,16 @@ VgSchedReturnCode VG_(scheduler) ( void )
          if (trc == VG_TRC_EBP_JMP_CLIENTREQ) {
             UInt reqno = *(UInt*)(VG_(threads)[tid].m_eax);
             /* VG_(printf)("request 0x%x\n", reqno); */
+
+            /* Are we really absolutely totally quitting? */
+            if (reqno == VG_USERREQ__LIBC_FREERES_DONE) {
+               if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
+                  VG_(message)(Vg_DebugMsg, 
+                     "__libc_freeres() done; really quitting!");
+               }
+               return VgSrc_ExitSyscall;
+            }
+
             do_client_request(tid);
             /* Following the request, we try and continue with the
                same thread if still runnable.  If not, go back to
@@ -1362,9 +1372,22 @@ VgSchedReturnCode VG_(scheduler) ( void )
             }
 #           endif
 
-            /* Is the client exiting for good? */
-            if (VG_(threads)[tid].m_eax == __NR_exit)
-               return VgSrc_ExitSyscall;
+            /* Deal with calling __libc_freeres() at exit.  When the
+               client does __NR_exit, it's exiting for good.  So we
+               then run VG_(__libc_freeres_wrapper).  That quits by
+               doing VG_USERREQ__LIBC_FREERES_DONE, and at that point
+               we really exit.  To be safe we nuke all other threads
+               currently running. */
+            if (VG_(threads)[tid].m_eax == __NR_exit) {
+               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 :) */
+            }
 
             /* Trap syscalls to __NR_sched_yield and just have this
                thread yield instead.  Not essential, just an
index a69f837c0ba6ca0de4b3ae4cba669910739310aa..0b044db6963af7dde2f652c9abd3879cfd0b06bd 100644 (file)
 # }
 
 
+#-------- Suppress errors appearing as a result of calling
+#-------- __libc_freeres()
+
+{
+   __twalk/*(Addr4)
+   Addr4
+   fun:__twalk
+}
+
+{
+   do_release_shlib/__twalk(Addr4)
+   Addr4
+   fun:do_release_shlib
+   fun:__twalk
+}
+
+{
+   __libc_freeres/free_mem/free(Free)
+   Free
+   fun:free
+   fun:free_mem
+   fun:__libc_freeres
+}
+
 #-------- Threading bugs?
 
 {
index 9e498e0518f39a49ca1023bf4824411de0dc810f..80bdae67149915bebef4be2484bedf01b4d9d53c 100644 (file)
@@ -552,6 +552,23 @@ int sigsuspend ( /* const sigset_t * */ void* mask)
    return -1;
 }
 
+
+/* ---------------------------------------------------------------------
+   Hook for running __libc_freeres once the program exits.
+   ------------------------------------------------------------------ */
+
+void VG_(__libc_freeres_wrapper)( void )
+{
+   int res;
+   extern void __libc_freeres(void);
+   __libc_freeres();
+   VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
+                           VG_USERREQ__LIBC_FREERES_DONE, 0, 0, 0, 0);
+   /*NOTREACHED*/
+   vg_assert(12345+54321 == 999999);
+}
+
+
 /*--------------------------------------------------------------------*/
 /*--- end                                         vg_clientfuncs.c ---*/
 /*--------------------------------------------------------------------*/
index 31ba8e92158e87313a3e50a4592b1936e4210ecb..0d38c92332e4b868f90b24cf6c80a275cdd44010 100644 (file)
@@ -519,6 +519,9 @@ extern Bool  VG_(is_empty_arena) ( ArenaId aid );
 #define VG_USERREQ__SET_FHSTACK_ENTRY       0x3027
 #define VG_USERREQ__GET_FHSTACK_ENTRY       0x3028
 
+/* Denote the finish of VG_(__libc_freeres_wrapper). */
+#define VG_USERREQ__LIBC_FREERES_DONE       0x3029
+
 /* Cosmetic ... */
 #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101
 /* Log a pthread error from client-space.  Cosmetic. */
@@ -529,6 +532,10 @@ In vg_constants.h:
 #define VG_USERREQ__SIGNAL_RETURNS          0x4001
 */
 
+/* The scheduler does need to know the address of it so it can be
+   called at program exit. */
+extern void VG_(__libc_freeres_wrapper)( void );
+
 
 /* ---------------------------------------------------------------------
    Constants pertaining to the simulated CPU state, VG_(baseBlock),
index 823c85908deee18865c738a625150e36dd3a1fbd..43b018917acac06b3044afd54c63d9dc14ebf4f5 100644 (file)
@@ -1337,6 +1337,16 @@ VgSchedReturnCode VG_(scheduler) ( void )
          if (trc == VG_TRC_EBP_JMP_CLIENTREQ) {
             UInt reqno = *(UInt*)(VG_(threads)[tid].m_eax);
             /* VG_(printf)("request 0x%x\n", reqno); */
+
+            /* Are we really absolutely totally quitting? */
+            if (reqno == VG_USERREQ__LIBC_FREERES_DONE) {
+               if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) {
+                  VG_(message)(Vg_DebugMsg, 
+                     "__libc_freeres() done; really quitting!");
+               }
+               return VgSrc_ExitSyscall;
+            }
+
             do_client_request(tid);
             /* Following the request, we try and continue with the
                same thread if still runnable.  If not, go back to
@@ -1362,9 +1372,22 @@ VgSchedReturnCode VG_(scheduler) ( void )
             }
 #           endif
 
-            /* Is the client exiting for good? */
-            if (VG_(threads)[tid].m_eax == __NR_exit)
-               return VgSrc_ExitSyscall;
+            /* Deal with calling __libc_freeres() at exit.  When the
+               client does __NR_exit, it's exiting for good.  So we
+               then run VG_(__libc_freeres_wrapper).  That quits by
+               doing VG_USERREQ__LIBC_FREERES_DONE, and at that point
+               we really exit.  To be safe we nuke all other threads
+               currently running. */
+            if (VG_(threads)[tid].m_eax == __NR_exit) {
+               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 :) */
+            }
 
             /* Trap syscalls to __NR_sched_yield and just have this
                thread yield instead.  Not essential, just an