to 4096, to possibly avoid deadlocks under very rare circumstances.
Is fully documented and commented.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@479
To find out if your program is blocking unexpectedly in the
<code>read</code> system call, run with
<code>--trace-syscalls=yes</code> flag.
+ <p>
+ <li><code>truncate-writes</code> Use this if you have a threaded
+ program which appears to unexpectedly block whilst writing
+ into a pipe. The effect is to modify all calls to
+ <code>write()</code> so that requests to write more than
+ 4096 bytes are treated as if they only requested a write of
+ 4096 bytes. Valgrind does this by changing the
+ <code>count</code> argument of <code>write()</code>, as
+ passed to the kernel, so that it is at most 4096. The
+ amount of data written will then be less than the client
+ program asked for, but the client should have a loop around
+ its <code>write()</code> call to check whether the requested
+ number of bytes have been written. If not, it should issue
+ further <code>write()</code> calls until all the data is
+ written.
+ <p>
+ This all sounds pretty dodgy to me, which is why I've made
+ this behaviour only happen on request. It is not the
+ default behaviour. At the time of writing this (30 June
+ 2002) I have only seen one example where this is necessary,
+ so either the problem is extremely rare or nobody is using
+ Valgrind :-)
+ <p>
+ On experimentation I see that <code>truncate-writes</code>
+ doesn't interact well with <code>ioctl-VTIME</code>, so you
+ probably don't want to try both at once.
+ <p>
+ As above, to find out if your program is blocking
+ unexpectedly in the <code>write()</code> system call, you
+ may find the <code>--trace-syscalls=yes
+ --trace-sched=yes</code> flags useful.
</ul>
</li><p>
To find out if your program is blocking unexpectedly in the
<code>read</code> system call, run with
<code>--trace-syscalls=yes</code> flag.
+ <p>
+ <li><code>truncate-writes</code> Use this if you have a threaded
+ program which appears to unexpectedly block whilst writing
+ into a pipe. The effect is to modify all calls to
+ <code>write()</code> so that requests to write more than
+ 4096 bytes are treated as if they only requested a write of
+ 4096 bytes. Valgrind does this by changing the
+ <code>count</code> argument of <code>write()</code>, as
+ passed to the kernel, so that it is at most 4096. The
+ amount of data written will then be less than the client
+ program asked for, but the client should have a loop around
+ its <code>write()</code> call to check whether the requested
+ number of bytes have been written. If not, it should issue
+ further <code>write()</code> calls until all the data is
+ written.
+ <p>
+ This all sounds pretty dodgy to me, which is why I've made
+ this behaviour only happen on request. It is not the
+ default behaviour. At the time of writing this (30 June
+ 2002) I have only seen one example where this is necessary,
+ so either the problem is extremely rare or nobody is using
+ Valgrind :-)
+ <p>
+ On experimentation I see that <code>truncate-writes</code>
+ doesn't interact well with <code>ioctl-VTIME</code>, so you
+ probably don't want to try both at once.
+ <p>
+ As above, to find out if your program is blocking
+ unexpectedly in the <code>write()</code> system call, you
+ may find the <code>--trace-syscalls=yes
+ --trace-sched=yes</code> flags useful.
</ul>
</li><p>
echo " --D1=<size>,<assoc>,<line_size> set D1 cache manually"
echo " --L2=<size>,<assoc>,<line_size> set L2 cache manually"
echo " --weird-hacks=hack1,hack2,... [no hacks selected]"
- echo " recognised hacks are: ioctl-VTIME"
+ echo " recognised hacks are: ioctl-VTIME truncate-writes"
echo ""
echo
echo " options for debugging Valgrind itself are:"
VG_(printf)("offending fd = %d\n", fd);
VG_(panic)("poll_for_ready_fds: multiple events on fd");
}
-
+
/* An I/O event completed for fd. Find the thread which
requested this. */
for (i = 0; i < VG_N_WAITING_FDS; i++) {
number, because the speculative call made by
sched_do_syscall() doesn't change %EAX in the case where the
call would have blocked. */
-
syscall_no = vg_waiting_fds[i].syscall_no;
vg_assert(syscall_no == VG_(threads)[tid].m_eax);
+
+ /* In a rare case pertaining to writing into a pipe, write()
+ will block when asked to write > 4096 bytes even though the
+ kernel claims, when asked via select(), that blocking will
+ not occur for a write on that fd. This can cause deadlocks.
+ An easy answer is to limit the size of the write to 4096
+ anyway and hope that the client program's logic can handle
+ the short write. That shoulds dubious to me, so we don't do
+ it by default. */
+ if (syscall_no == __NR_write
+ && VG_(threads)[tid].m_edx /* arg3, count */ > 4096
+ && VG_(strstr)(VG_(clo_weird_hacks), "truncate-writes") != NULL) {
+ /* VG_(printf)("truncate write from %d to 4096\n",
+ VG_(threads)[tid].m_edx ); */
+ VG_(threads)[tid].m_edx = 4096;
+ }
+
KERNEL_DO_SYSCALL(tid,res);
VG_(check_known_blocking_syscall)(tid, syscall_no, &res /* POST */);
To find out if your program is blocking unexpectedly in the
<code>read</code> system call, run with
<code>--trace-syscalls=yes</code> flag.
+ <p>
+ <li><code>truncate-writes</code> Use this if you have a threaded
+ program which appears to unexpectedly block whilst writing
+ into a pipe. The effect is to modify all calls to
+ <code>write()</code> so that requests to write more than
+ 4096 bytes are treated as if they only requested a write of
+ 4096 bytes. Valgrind does this by changing the
+ <code>count</code> argument of <code>write()</code>, as
+ passed to the kernel, so that it is at most 4096. The
+ amount of data written will then be less than the client
+ program asked for, but the client should have a loop around
+ its <code>write()</code> call to check whether the requested
+ number of bytes have been written. If not, it should issue
+ further <code>write()</code> calls until all the data is
+ written.
+ <p>
+ This all sounds pretty dodgy to me, which is why I've made
+ this behaviour only happen on request. It is not the
+ default behaviour. At the time of writing this (30 June
+ 2002) I have only seen one example where this is necessary,
+ so either the problem is extremely rare or nobody is using
+ Valgrind :-)
+ <p>
+ On experimentation I see that <code>truncate-writes</code>
+ doesn't interact well with <code>ioctl-VTIME</code>, so you
+ probably don't want to try both at once.
+ <p>
+ As above, to find out if your program is blocking
+ unexpectedly in the <code>write()</code> system call, you
+ may find the <code>--trace-syscalls=yes
+ --trace-sched=yes</code> flags useful.
</ul>
</li><p>
To find out if your program is blocking unexpectedly in the
<code>read</code> system call, run with
<code>--trace-syscalls=yes</code> flag.
+ <p>
+ <li><code>truncate-writes</code> Use this if you have a threaded
+ program which appears to unexpectedly block whilst writing
+ into a pipe. The effect is to modify all calls to
+ <code>write()</code> so that requests to write more than
+ 4096 bytes are treated as if they only requested a write of
+ 4096 bytes. Valgrind does this by changing the
+ <code>count</code> argument of <code>write()</code>, as
+ passed to the kernel, so that it is at most 4096. The
+ amount of data written will then be less than the client
+ program asked for, but the client should have a loop around
+ its <code>write()</code> call to check whether the requested
+ number of bytes have been written. If not, it should issue
+ further <code>write()</code> calls until all the data is
+ written.
+ <p>
+ This all sounds pretty dodgy to me, which is why I've made
+ this behaviour only happen on request. It is not the
+ default behaviour. At the time of writing this (30 June
+ 2002) I have only seen one example where this is necessary,
+ so either the problem is extremely rare or nobody is using
+ Valgrind :-)
+ <p>
+ On experimentation I see that <code>truncate-writes</code>
+ doesn't interact well with <code>ioctl-VTIME</code>, so you
+ probably don't want to try both at once.
+ <p>
+ As above, to find out if your program is blocking
+ unexpectedly in the <code>write()</code> system call, you
+ may find the <code>--trace-syscalls=yes
+ --trace-sched=yes</code> flags useful.
</ul>
</li><p>
echo " --D1=<size>,<assoc>,<line_size> set D1 cache manually"
echo " --L2=<size>,<assoc>,<line_size> set L2 cache manually"
echo " --weird-hacks=hack1,hack2,... [no hacks selected]"
- echo " recognised hacks are: ioctl-VTIME"
+ echo " recognised hacks are: ioctl-VTIME truncate-writes"
echo ""
echo
echo " options for debugging Valgrind itself are:"
VG_(printf)("offending fd = %d\n", fd);
VG_(panic)("poll_for_ready_fds: multiple events on fd");
}
-
+
/* An I/O event completed for fd. Find the thread which
requested this. */
for (i = 0; i < VG_N_WAITING_FDS; i++) {
number, because the speculative call made by
sched_do_syscall() doesn't change %EAX in the case where the
call would have blocked. */
-
syscall_no = vg_waiting_fds[i].syscall_no;
vg_assert(syscall_no == VG_(threads)[tid].m_eax);
+
+ /* In a rare case pertaining to writing into a pipe, write()
+ will block when asked to write > 4096 bytes even though the
+ kernel claims, when asked via select(), that blocking will
+ not occur for a write on that fd. This can cause deadlocks.
+ An easy answer is to limit the size of the write to 4096
+ anyway and hope that the client program's logic can handle
+ the short write. That shoulds dubious to me, so we don't do
+ it by default. */
+ if (syscall_no == __NR_write
+ && VG_(threads)[tid].m_edx /* arg3, count */ > 4096
+ && VG_(strstr)(VG_(clo_weird_hacks), "truncate-writes") != NULL) {
+ /* VG_(printf)("truncate write from %d to 4096\n",
+ VG_(threads)[tid].m_edx ); */
+ VG_(threads)[tid].m_edx = 4096;
+ }
+
KERNEL_DO_SYSCALL(tid,res);
VG_(check_known_blocking_syscall)(tid, syscall_no, &res /* POST */);