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 ---*/
/*--------------------------------------------------------------------*/
#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. */
#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),
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
}
# 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
# }
+#-------- 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?
{
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 ---*/
/*--------------------------------------------------------------------*/
#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. */
#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),
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
}
# 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