Index: llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py =================================================================== --- llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py +++ llvm/trunk/test/tools/llvm-symbolizer/Inputs/flush-output.py @@ -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() Index: llvm/trunk/test/tools/llvm-symbolizer/flush-output.s =================================================================== --- llvm/trunk/test/tools/llvm-symbolizer/flush-output.s +++ llvm/trunk/test/tools/llvm-symbolizer/flush-output.s @@ -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 Index: llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp =================================================================== --- llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -246,7 +246,6 @@ } if (ClOutputStyle == DIPrinter::OutputStyle::LLVM) outs() << "\n"; - outs().flush(); } int main(int argc, char **argv) { @@ -291,8 +290,10 @@ 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);