[llvm] r362511 - [llvm-symbolizer] Flush output on bad input

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 4 08:34:58 PDT 2019


Author: jhenderson
Date: Tue Jun  4 08:34:58 2019
New Revision: 362511

URL: http://llvm.org/viewvc/llvm-project?rev=362511&view=rev
Log:
[llvm-symbolizer] Flush output on bad input

One way of using llvm-symbolizer is to interactively within a process
write a line from a parent process to llvm-symbolizer's stdin, and then
read the output, then write the next line, read, etc. This worked as
long as all the lines were good. However, this didn't work prior to this
patch if any of the inputs were bad inputs, because the output is not
flushed after a bad input, meaning the parent process is sat waiting for
output, whilst llvm-symbolizer is sat waiting for input. This patch
flushes the output after every invocation of symbolizeInput when reading
from stdin. It also removes unnecessary flushing when llvm-symbolizer is
not reading addresses from stdin, which should give a slight performance
boost in these situations.

Reviewed by: ikudrin

Differential Revision: https://reviews.llvm.org/D62371

Added:
    llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py
    llvm/trunk/test/tools/llvm-symbolizer/flush-output.s
Modified:
    llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp

Added: llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py?rev=362511&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py (added)
+++ llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py Tue Jun  4 08:34:58 2019
@@ -0,0 +1,24 @@
+from __future__ import print_function
+import os
+import subprocess
+import sys
+import threading
+
+def kill_subprocess(process):
+    process.kill()
+    os._exit(1)
+
+# Pass -f=none and --output-style=GNU to get only one line of output per input.
+cmd = subprocess.Popen([sys.argv[1],
+                        '--obj=' + sys.argv[2],
+                        '-f=none',
+                        '--output-style=GNU'], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+watchdog = threading.Timer(20, kill_subprocess, args=[cmd])
+watchdog.start()
+cmd.stdin.write(b'0\n')
+cmd.stdin.flush()
+print(cmd.stdout.readline())
+cmd.stdin.write(b'bad\n')
+cmd.stdin.flush()
+print(cmd.stdout.readline())
+watchdog.cancel()

Added: llvm/trunk/test/tools/llvm-symbolizer/flush-output.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-symbolizer/flush-output.s?rev=362511&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-symbolizer/flush-output.s (added)
+++ llvm/trunk/test/tools/llvm-symbolizer/flush-output.s Tue Jun  4 08:34:58 2019
@@ -0,0 +1,17 @@
+# REQUIRES: x86-registered-target
+
+## If a process spawns llvm-symbolizer, and wishes to feed it addresses one at a
+## time, llvm-symbolizer needs to flush its output after each input has been
+## processed or the parent process will not be able to read the output and may
+## deadlock. This test runs a script that simulates this situation for both a
+## a good and bad input.
+
+foo:
+    nop
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -g
+# RUN: %python %p/Inputs/flush-output.py llvm-symbolizer %t.o \
+# RUN:   | FileCheck %s
+
+# CHECK: flush-output.s:10
+# CHECK: bad

Modified: llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp?rev=362511&r1=362510&r2=362511&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp (original)
+++ llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp Tue Jun  4 08:34:58 2019
@@ -246,7 +246,6 @@ static void symbolizeInput(StringRef Inp
   }
   if (ClOutputStyle == DIPrinter::OutputStyle::LLVM)
     outs() << "\n";
-  outs().flush();
 }
 
 int main(int argc, char **argv) {
@@ -291,8 +290,10 @@ int main(int argc, char **argv) {
     const int kMaxInputStringLength = 1024;
     char InputString[kMaxInputStringLength];
 
-    while (fgets(InputString, sizeof(InputString), stdin))
+    while (fgets(InputString, sizeof(InputString), stdin)) {
       symbolizeInput(InputString, Symbolizer, Printer);
+      outs().flush();
+    }
   } else {
     for (StringRef Address : ClInputAddresses)
       symbolizeInput(Address, Symbolizer, Printer);




More information about the llvm-commits mailing list