{"thread":{"id":"56939","subject":"[PATCH] trace2: disable tr2_dst before warning on write errors","startedAt":"2021-11-18T22:01:45Z","lastAt":"2021-11-18T22:01:45Z","messageCount":1,"participants":["Josh Steadmon"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"441663","messageId":"5a9e49e7f1540d762374382e1769edf112cf093f.1637272706.git.steadmon@google.com","threadId":"56939","inReplyTo":null,"subject":"[PATCH] trace2: disable tr2_dst before warning on write errors","fromName":"Josh Steadmon","fromEmail":"steadmon@google.com","sentAt":"2021-11-18T22:01:41Z","receivedAt":"2021-11-18T22:01:45Z","isPatch":true,"sender":{"key":"steadmon@google.com","avatar":"https://avatars.githubusercontent.com/u/2654920?v=4"},"body":"If writing a trace2 message fails, we optionally warn the user of this\nfact. However, in 0ee10fd (usage: add trace2 entry upon warning(),\n2020-11-23), we added a trace entry to the warning() function. This\nmeans that we can enter an infinite loop of failing trace2 writes and\nwarnings. Fix this by disabling the failing trace2 destination before\nissuing the warning.\n\nAdditionally, trace2 sets a default SIGPIPE handler\n(tr2main_signal_handler) when it is initialized. This handler generates\nits own trace2 messages when a signal is received. If a trace2 write\nfails due to a broken pipe, this handler will run and then cause another\nfailed write. Fix this by temporarily ignoring SIGPIPE while writing\ntrace2 messages. This is safe because the write will still fail, and we\nwill disable the failing destination.\n\nSigned-off-by: Josh Steadmon <steadmon@google.com>\n---\n trace2/tr2_dst.c | 9 +++++++--\n 1 file changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/trace2/tr2_dst.c b/trace2/tr2_dst.c\nindex bda283e7f4..8a21dd2972 100644\n--- a/trace2/tr2_dst.c\n+++ b/trace2/tr2_dst.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"sigchain.h\"\n #include \"trace2/tr2_dst.h\"\n #include \"trace2/tr2_sid.h\"\n #include \"trace2/tr2_sysenv.h\"\n@@ -360,6 +361,7 @@ int tr2_dst_trace_want(struct tr2_dst *dst)\n void tr2_dst_write_line(struct tr2_dst *dst, struct strbuf *buf_line)\n {\n \tint fd = tr2_dst_get_trace_fd(dst);\n+\tssize_t bytes;\n \n \tstrbuf_complete_line(buf_line); /* ensure final NL on buffer */\n \n@@ -378,12 +380,15 @@ void tr2_dst_write_line(struct tr2_dst *dst, struct strbuf *buf_line)\n \t *\n \t * If we get an IO error, just close the trace dst.\n \t */\n-\tif (write(fd, buf_line->buf, buf_line->len) >= 0)\n+\tsigchain_push(SIGPIPE, SIG_IGN);\n+\tbytes = write(fd, buf_line->buf, buf_line->len);\n+\tsigchain_pop(SIGPIPE);\n+\tif (bytes >= 0)\n \t\treturn;\n \n+\ttr2_dst_trace_disable(dst);\n \tif (tr2_dst_want_warning())\n \t\twarning(\"unable to write trace to '%s': %s\",\n \t\t\ttr2_sysenv_display_name(dst->sysenv_var),\n \t\t\tstrerror(errno));\n-\ttr2_dst_trace_disable(dst);\n }\n\nbase-commit: cd3e606211bb1cf8bc57f7d76bab98cc17a150bc\n-- \n2.34.0.rc2.393.gf8c9666880-goog\n\n"}]}