diff mbox series

trace2: disable tr2_dst before warning on write errors

Message ID 5a9e49e7f1540d762374382e1769edf112cf093f.1637272706.git.steadmon@google.com (mailing list archive)
State Accepted
Commit c5b1e5ddecb20461c1ae2a49706fea5a654d2223
Headers show
Series trace2: disable tr2_dst before warning on write errors | expand

Commit Message

Josh Steadmon Nov. 18, 2021, 10:01 p.m. UTC
If writing a trace2 message fails, we optionally warn the user of this
fact. However, in 0ee10fd (usage: add trace2 entry upon warning(),
2020-11-23), we added a trace entry to the warning() function. This
means that we can enter an infinite loop of failing trace2 writes and
warnings. Fix this by disabling the failing trace2 destination before
issuing the warning.

Additionally, trace2 sets a default SIGPIPE handler
(tr2main_signal_handler) when it is initialized. This handler generates
its own trace2 messages when a signal is received. If a trace2 write
fails due to a broken pipe, this handler will run and then cause another
failed write. Fix this by temporarily ignoring SIGPIPE while writing
trace2 messages. This is safe because the write will still fail, and we
will disable the failing destination.

Signed-off-by: Josh Steadmon <steadmon@google.com>
---
 trace2/tr2_dst.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)


base-commit: cd3e606211bb1cf8bc57f7d76bab98cc17a150bc
diff mbox series

Patch

diff --git a/trace2/tr2_dst.c b/trace2/tr2_dst.c
index bda283e7f4..8a21dd2972 100644
--- a/trace2/tr2_dst.c
+++ b/trace2/tr2_dst.c
@@ -1,4 +1,5 @@ 
 #include "cache.h"
+#include "sigchain.h"
 #include "trace2/tr2_dst.h"
 #include "trace2/tr2_sid.h"
 #include "trace2/tr2_sysenv.h"
@@ -360,6 +361,7 @@  int tr2_dst_trace_want(struct tr2_dst *dst)
 void tr2_dst_write_line(struct tr2_dst *dst, struct strbuf *buf_line)
 {
 	int fd = tr2_dst_get_trace_fd(dst);
+	ssize_t bytes;
 
 	strbuf_complete_line(buf_line); /* ensure final NL on buffer */
 
@@ -378,12 +380,15 @@  void tr2_dst_write_line(struct tr2_dst *dst, struct strbuf *buf_line)
 	 *
 	 * If we get an IO error, just close the trace dst.
 	 */
-	if (write(fd, buf_line->buf, buf_line->len) >= 0)
+	sigchain_push(SIGPIPE, SIG_IGN);
+	bytes = write(fd, buf_line->buf, buf_line->len);
+	sigchain_pop(SIGPIPE);
+	if (bytes >= 0)
 		return;
 
+	tr2_dst_trace_disable(dst);
 	if (tr2_dst_want_warning())
 		warning("unable to write trace to '%s': %s",
 			tr2_sysenv_display_name(dst->sysenv_var),
 			strerror(errno));
-	tr2_dst_trace_disable(dst);
 }