Problem with closing piped output due to msvctricks.exe
mstorsjo opened this issue · 1 comments
CC @huangqinjin
Since the introduction of the msvctricks.exe binary, closing the output pipe of the compiler causes hangs.
To reproduce:
$ echo '#include <vector>' > file.cpp
$ cl -E file.cpp | less
Within less, type q
to stop reading the input (after only consuming a screenful of output, from the preprocessing output which is large enough to block the pipe buffers). Normally I would expect all processes to exit at this point (possibly with some complaints due to the broken pipe). With msvctricks.exe in place, I instead get a hang. If I remove msvctricks.exe so that this only uses the redirections done in wine-msvc.sh
, this works as expected.
I reproduced the issue.
demo.cpp
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE* f = argv[1] ? fopen(argv[1], "w") : stdout;
for (int i = 0; i < 100000; ++i)
fprintf(f, "%d\n", i);
return 119;
}
g++ demo.cpp -o demo
/opt/msvc/bin/x64/cl demo.cpp
Use stdout
$ ./demo | head -n1 >/dev/null; echo "${PIPESTATUS[@]}"
141 0
$ wine64 demo.exe | head -n1 >/dev/null; echo "${PIPESTATUS[@]}"
119 0
- Linux app exits with 141 = 128 +
SIGPIPE(13)
. - Win32 app ignores
SIGPIPE
and exits normally.
Use FIFO
$ mkfifo fifo
$ { cat fifo || echo "cat $?">&2 & ./demo fifo || echo "demo $?">&2; } | head -n1 >/dev/null
cat 141
demo 141
$ { cat fifo || echo "cat $?">&2 & wine64 demo.exe fifo || echo "demo $?">&2; } | head -n1 >/dev/null
cat 141
<hangs>
$ { cat fifo || echo "cat $?">&2 & wine64 demo.exe >fifo || echo "demo $?">&2; } | head -n1 >/dev/null
cat 141
demo 119
Wine handles SIGPIPE
differently for stdout
and other fds (logs are from strace
output):
SIGPIPE
is silently ignored onstdout
and app doesn't get terminated.write(7, "0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10"..., 5119) = 5119 write(7, "038\r\n1039\r\n1040\r\n1", 18) = 18 write(7, "041\r\n1042\r\n1043\r\n1044\r\n1045\r\n104"..., 4915) = -1 EPIPE (Broken pipe) --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=17632, si_uid=1000} --- write(7, "61861\r\n1862\r\n1863\r\n1864\r\n1865\r\n1"..., 4915) = -1 EPIPE (Broken pipe) --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=17632, si_uid=1000} --- ...
- app is blocking on
poll
after the other end of the pipe is closed:... write(11, "233\r\n9234\r\n9235\r\n9236\r\n9237\r\n923"..., 4906) = 4906 write(11, "3\r\n10044\r\n10045\r\n10046\r\n10047\r\n1"..., 4779) = 683 poll([{fd=11, events=POLLOUT}], 1, -1)
The proposed solution is to manually kill
wine after cat
exits.