[PATCH] D124607: Add an error message to the default SIGPIPE handler
Damian Malarczyk via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 1 03:29:05 PDT 2022
dmcyk added a comment.
Thanks for trying it out @nemanjai, I can reproduce this locally indeed.
In D124607#3536577 <https://reviews.llvm.org/D124607#3536577>, @nemanjai wrote:
> In D124607#3536329 <https://reviews.llvm.org/D124607#3536329>, @jhenderson wrote:
>
>> Both llvm-symbolizer and llvm-cxxfilt, if called without positional arguments, are run interactively, essentially taking a line of input then writing some output before waiting for more input. This would allow you to force output to be written (by writing to stdin) after the pipe has been closed. Maybe that'll solve the issue, although I'm not sure I understand why the python script doesn't work in its current form: llvm-nm should try to write many bytes of output (> 1 byte), but the pipe is closed after the very first byte is written. Before going and changing the script, I'd like to understand whether this statement is actually true, and if so, why:
>>
>>> That does not appear to be enough. You can either run a tool that runs longer or run llvm-nm with something that produces more output.
>
> If you have an idea for how I can verify this, I'd love to help. Without any tracing/debugging as proof, the way I guess I reason about it is that the process writes to the pipe asynchronously without regard to how much is read from the pipe. So if the write finishes before the pipe is closed, it finishes. Namely, reading a single byte from the pipe rather than all of them does not prevent all the bytes from being written to it before it is closed.
> As I said, I am not sure why the test only works when there is more output. All I know for sure is that I've tried it on multiple machines with a shared library build with the same results.
I think you're right about llvm-nm being able to write out all the bytes before the pipe is closed. Kernel buffers writes to a pipe, if nm's output doesn't exceed the buffer size it may finish running before stdout is closed.
In my system it looks like the kernel's pipe buffer fits 65k bytes, here's how I tested it:
$ cat sigtest.c
#include <signal.h>
#include <sys/signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
void Action(int sig, siginfo_t* info, void* context) {
fprintf(stderr, "sig action\n");
exit(78);
}
int main(int argc, char** argv) {
struct sigaction orig;
struct sigaction handler;
handler.sa_flags = SA_SIGINFO;
handler.sa_sigaction = Action;
sigaction(SIGPIPE, &handler, &orig);
int limit = 1000;
if (argc > 1) {
limit = atoi(argv[1]);
}
for (int i = 0; i < limit; ++i) {
write(1, "a", 1);
fprintf(stderr, "wrote nth: %d\n", i + 1);
}
}
$ cat test.py
import subprocess
import sys
import time
with subprocess.Popen([sys.argv[1], sys.argv[2]], stdout=subprocess.PIPE) as process:
time.sleep(5);
print("- finished sleep")
process.stdout.read(1)
process.stdout.close()
print("- exit: ", process.returncode)
sys.exit(process.returncode)
$ clang sigtest.c
$ python3 test.py $PWD/a.out 65536
wrote nth: 65535
wrote nth: 65536
- finished sleep
- exit: 0
This finishes writing all the bytes before the first byte is even read and always exits with a 0 code.
But when I bump the number of bytes it hangs trying to write the 65537th byte, sometimes it still manages to write it before the pipe is closed:
$ python3 test.py $PWD/a.out 65537
wrote nth: 65535
wrote nth: 65536
- finished sleep
wrote nth: 65537
- exit: 0
and sometimes stdout is closed faster:
$ python3 test.py $PWD/a.out 65537
wrote nth: 65536
- finished sleep
sig action
- exit: 78
llvm-nm won't get the signal without a guarantee that stdout is closed before it tries to write to it, so I've moved the test case to use llvm-cxxfilt. Thanks for the tip @jhenderson.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D124607/new/
https://reviews.llvm.org/D124607
More information about the llvm-commits
mailing list