/memcheck/tests/memalign2
/memcheck/tests/memalign_test
/memcheck/tests/memcmptest
+/memcheck/tests/memmem
/memcheck/tests/mempool
/memcheck/tests/mempool2
/memcheck/tests/metadata
* ==================== CORE CHANGES ===================
+* The option "--vgdb-stop-at=event1,event2,..." accepts the new value abexit.
+ This indicates to invoke gdbserver when your program exits abnormally
+ (i.e. with a non zero exit code).
* Fix Rust v0 name demangling.
* The Linux rseq syscall is now implemented as (silently) returning ENOSYS.
* Add FreeBSD syscall wrappers for __specialfd and __realpathat.
n-i-bz Implement vgdb invoker on FreeBSD
458845 PowerPC: The L field for the dcbf and sync instruction should be
3 bits in ISA 3.1.
+459031 Documentation on --error-exitcode incomplete
To see details of a given bug, visit
https://bugs.kde.org/show_bug.cgi?id=XXXXXX
" and follow the on-screen directions\n"
" --vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]\n"
" where event is one of:\n"
-" startup exit valgrindabexit all none\n"
+" startup exit abexit valgrindabexit all none\n"
" --track-fds=no|yes|all track open file descriptors? [no]\n"
" all includes reporting stdin, stdout and stderr\n"
" --time-stamp=no|yes add timestamps to log messages? [no]\n"
else if VG_INT_CLOM (cloPD, arg, "--vgdb-poll", VG_(clo_vgdb_poll)) {}
else if VG_INT_CLOM (cloPD, arg, "--vgdb-error", VG_(clo_vgdb_error)) {}
else if VG_USET_CLOM (cloPD, arg, "--vgdb-stop-at",
- "startup,exit,valgrindabexit",
+ "startup,exit,abexit,valgrindabexit",
VG_(clo_vgdb_stop_at)) {}
else if VG_STR_CLO (arg, "--vgdb-prefix", VG_(clo_vgdb_prefix)) {
VG_(arg_vgdb_prefix) = arg;
vg_assert(0);
}
+/* Return the exit code to use when tid exits, depending on the tid os_state
+ exit code and the clo options controlling valgrind exit code. */
+static
+Int tid_exit_code (ThreadId tid)
+{
+ if (VG_(clo_error_exitcode) > 0 && VG_(get_n_errs_found)() > 0)
+ /* Change the application return code to user's return code,
+ if an error was found */
+ return VG_(clo_error_exitcode);
+ else
+ /* otherwise, return the client's exit code, in the normal
+ way. */
+ return VG_(threads)[tid].os_state.exitcode;
+}
+
/* Do everything which needs doing when the last thread exits or when
a thread exits requesting a complete process exit.
}
/* Final call to gdbserver, if requested. */
- if (VG_(gdbserver_stop_at) (VgdbStopAt_Exit)) {
- VG_(umsg)("(action at exit) vgdb me ... \n");
+ if (VG_(gdbserver_stop_at) (VgdbStopAt_Abexit)
+ && tid_exit_code (tid) != 0) {
+ VG_(umsg)("(action at abexit, exit code %d) vgdb me ... \n",
+ tid_exit_code (tid));
+ VG_(gdbserver) (tid);
+ } else if (VG_(gdbserver_stop_at) (VgdbStopAt_Exit)) {
+ VG_(umsg)("(action at exit, exit code %d) vgdb me ... \n",
+ tid_exit_code (tid));
VG_(gdbserver) (tid);
}
VG_(threads)[tid].status = VgTs_Empty;
switch (tids_schedretcode) {
case VgSrc_ExitThread: /* the normal way out (Linux, Solaris) */
case VgSrc_ExitProcess: /* the normal way out (Darwin) */
- /* Change the application return code to user's return code,
- if an error was found */
- if (VG_(clo_error_exitcode) > 0
- && VG_(get_n_errs_found)() > 0) {
- VG_(client_exit)( VG_(clo_error_exitcode) );
- } else {
- /* otherwise, return the client's exit code, in the normal
- way. */
- VG_(client_exit)( VG_(threads)[tid].os_state.exitcode );
- }
+ VG_(client_exit)(tid_exit_code (tid));
/* NOT ALIVE HERE! */
VG_(core_panic)("entered the afterlife in main() -- ExitT/P");
break; /* what the hell :) */
{
VgSchedReturnCode ret;
ThreadId tid = (ThreadId)tidW;
+ Int lwpid = VG_(gettid)();
ThreadState* tst = VG_(get_ThreadState)(tid);
- VG_(debugLog)(1, "syswrap-darwin",
- "thread_wrapper(tid=%u): entry\n",
- tid);
+ VG_(debugLog)(1, "syswrap-darwin",
+ "thread_wrapper(tid=%u,lwpid=%d): entry\n",
+ tid, lwpid);
vg_assert(tst->status == VgTs_Init);
VG_TRACK(pre_thread_first_insn, tid);
- tst->os_state.lwpid = VG_(gettid)();
+ tst->os_state.lwpid = lwpid;
tst->os_state.threadgroup = VG_(getpid)();
/* Thread created with all signals blocked; scheduler will set the
ret = VG_(scheduler)(tid);
vg_assert(VG_(is_exiting)(tid));
-
+
vg_assert(tst->status == VgTs_Runnable);
vg_assert(VG_(is_running_thread)(tid));
- VG_(debugLog)(1, "syswrap-darwin",
- "thread_wrapper(tid=%u): done\n",
- tid);
+ VG_(debugLog)(1, "syswrap-darwin",
+ "thread_wrapper(tid=%u,lwpid=%d): done\n",
+ tid, lwpid);
/* Return to caller, still holding the lock. */
return ret;
{
VgSchedReturnCode ret;
ThreadId tid = (ThreadId)tidW;
+ Int lwpid = VG_(gettid)();
ThreadState* tst = VG_(get_ThreadState)(tid);
VG_(debugLog)(1, "syswrap-freebsd",
- "thread_wrapper(tid=%u): entry\n",
- tid);
+ "thread_wrapper(tid=%u,lwpid=%d): entry\n",
+ tid, lwpid);
vg_assert(tst->status == VgTs_Init);
VG_TRACK(pre_thread_first_insn, tid);
- tst->os_state.lwpid = VG_(gettid)();
+ tst->os_state.lwpid = lwpid;
/* Set the threadgroup for real. This overwrites the provisional value set
in do_clone(). See comments in do_clone for background, also #226116. */
tst->os_state.threadgroup = VG_(getpid)();
vg_assert(VG_(is_running_thread)(tid));
VG_(debugLog)(1, "syswrap-freebsd",
- "thread_wrapper(tid=%u): exit, schedreturncode %s\n",
- tid, VG_(name_of_VgSchedReturnCode)(ret));
+ "thread_wrapper(tid=%u,lwpid=%d): exit, schedreturncode %s\n",
+ tid, lwpid, VG_(name_of_VgSchedReturnCode)(ret));
/* Return to caller, still holding the lock. */
return ret;
{
VgSchedReturnCode ret;
ThreadId tid = (ThreadId)tidW;
+ Int lwpid = VG_(gettid)();
ThreadState* tst = VG_(get_ThreadState)(tid);
- VG_(debugLog)(1, "syswrap-linux",
- "thread_wrapper(tid=%u): entry\n",
- tid);
+ VG_(debugLog)(1, "syswrap-linux",
+ "thread_wrapper(tid=%u,lwpid=%d): entry\n",
+ tid, lwpid);
vg_assert(tst->status == VgTs_Init);
VG_TRACK(pre_thread_first_insn, tid);
- tst->os_state.lwpid = VG_(gettid)();
+ tst->os_state.lwpid = lwpid;
/* Set the threadgroup for real. This overwrites the provisional value set
in do_clone(). See comments in do_clone for background, also #226116. */
tst->os_state.threadgroup = VG_(getpid)();
ret = VG_(scheduler)(tid);
vg_assert(VG_(is_exiting)(tid));
-
+
vg_assert(tst->status == VgTs_Runnable);
vg_assert(VG_(is_running_thread)(tid));
- VG_(debugLog)(1, "syswrap-linux",
- "thread_wrapper(tid=%u): exit, schedreturncode %s\n",
- tid, VG_(name_of_VgSchedReturnCode)(ret));
+ VG_(debugLog)(1, "syswrap-linux",
+ "thread_wrapper(tid=%u,lwpid=%d): exit, schedreturncode %s\n",
+ tid, lwpid, VG_(name_of_VgSchedReturnCode)(ret));
/* Return to caller, still holding the lock. */
return ret;
{
VgSchedReturnCode ret;
ThreadId tid = (ThreadId)tidW;
+ Int lwpid = VG_(gettid)();
ThreadState *tst = VG_(get_ThreadState)(tid);
VG_(debugLog)(1, "syswrap-solaris",
- "thread_wrapper(tid=%u): entry\n",
- tid);
+ "thread_wrapper(tid=%u,lwpid=%d): entry\n",
+ tid, lwpid);
vg_assert(tst->status == VgTs_Init);
here would be way too early - new thread has no stack, yet. */
}
- tst->os_state.lwpid = VG_(gettid)();
+ tst->os_state.lwpid = lwpid;
tst->os_state.threadgroup = VG_(getpid)();
/* Thread created with all signals blocked; scheduler will set the
vg_assert(VG_(is_running_thread)(tid));
VG_(debugLog)(1, "syswrap-solaris",
- "thread_wrapper(tid=%u): exit, schedreturncode %s\n",
- tid, VG_(name_of_VgSchedReturnCode)(ret));
+ "thread_wrapper(tid=%u,lwpid=%d): exit, schedreturncode %s\n",
+ tid, lwpid, VG_(name_of_VgSchedReturnCode)(ret));
/* Return to caller, still holding the lock. */
return ret;
/* Specify when Valgrind gdbserver stops the execution and wait
for a GDB to connect. */
typedef
- enum { // Stop :
- VgdbStopAt_Startup, // just before the client starts to execute.
- VgdbStopAt_Exit, // just before the client exits.
- VgdbStopAt_ValgrindAbExit // on abnormal valgrind exit.
+ enum { // Stop just before ...
+ VgdbStopAt_Startup, // ... the client starts to execute.
+ VgdbStopAt_Exit, // ... the client exits with any exit code..
+ VgdbStopAt_Abexit, // ... the client exits with a non 0 exit code.
+ VgdbStopAt_ValgrindAbExit // ... an abnormal valgrind exit.
}
VgdbStopAt;
// Build mask to check or set VgdbStop_At a membership
for other events, specified in one of the following ways: </para>
<itemizedlist>
<listitem><para>a comma separated list of one or more of
- <option>startup exit valgrindabexit</option>.</para>
+ <option>startup exit abexit valgrindabexit</option>.</para>
<para>The values <option>startup</option> <option>exit</option>
- <option>valgrindabexit</option> respectively indicate to
- invoke gdbserver before your program is executed, after the
- last instruction of your program, on Valgrind abnormal exit
- (e.g. internal error, out of memory, ...).</para>
+ <option>valgrindabexit</option> respectively indicate to invoke
+ gdbserver before your program is executed, after the last instruction
+ of your program, on Valgrind abnormal exit (e.g. internal error, out
+ of memory, ...).</para>
+
+ <para>The option <option>abexit</option> is similar to <option>exit</option>
+ but tells to invoke gdbserver only when your application exits abnormally
+ (i.e. with an exit code different of 0). </para>
<para>Note: <option>startup</option> and
<option>--vgdb-error=0</option> will both cause Valgrind
<listitem><para><option>all</option> to specify the complete set.
It is equivalent to
- <option>--vgdb-stop-at=startup,exit,valgrindabexit</option>.</para>
+ <option>--vgdb-stop-at=startup,exit,abexit,valgrindabexit</option>.</para>
</listitem>
<listitem><para><option>none</option> for the empty set.</para>
that value is returned instead, if Valgrind detects any errors.
This is useful for using Valgrind as part of an automated test
suite, since it makes it easy to detect test cases for which
- Valgrind has reported errors, just by inspecting return codes.</para>
+ Valgrind has reported errors, just by inspecting return codes.
+ When set to a nonzero value and Valgrind detects no error,
+ the return value of Valgrind will be the return value of the
+ program being simulated.
+ </para>
</listitem>
</varlistentry>
starting ...
exiting ...
-(action at exit) vgdb me ...
+(action at exit, exit code 1) vgdb me ...
and follow the on-screen directions
--vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]
where event is one of:
- startup exit valgrindabexit all none
+ startup exit abexit valgrindabexit all none
--track-fds=no|yes|all track open file descriptors? [no]
all includes reporting stdin, stdout and stderr
--time-stamp=no|yes add timestamps to log messages? [no]
and follow the on-screen directions
--vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]
where event is one of:
- startup exit valgrindabexit all none
+ startup exit abexit valgrindabexit all none
--track-fds=no|yes|all track open file descriptors? [no]
all includes reporting stdin, stdout and stderr
--time-stamp=no|yes add timestamps to log messages? [no]