[clangd] Shutdown cleanly on signals.

Summary:
This avoids leaking PCH files if editors don't use the LSP shutdown protocol.

This is one fix for https://github.com/clangd/clangd/issues/209
(Though I think we should *also* be unlinking the files)

Reviewers: kadircet, jfb

Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, jfb, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D70684
diff --git a/clang-tools-extra/clangd/JSONTransport.cpp b/clang-tools-extra/clangd/JSONTransport.cpp
index 4921035..6351b80 100644
--- a/clang-tools-extra/clangd/JSONTransport.cpp
+++ b/clang-tools-extra/clangd/JSONTransport.cpp
@@ -7,8 +7,10 @@
 //===----------------------------------------------------------------------===//
 #include "Logger.h"
 #include "Protocol.h" // For LSPError
+#include "Shutdown.h"
 #include "Transport.h"
 #include "llvm/Support/Errno.h"
+#include "llvm/Support/Error.h"
 
 namespace clang {
 namespace clangd {
@@ -81,6 +83,10 @@
 
   llvm::Error loop(MessageHandler &Handler) override {
     while (!feof(In)) {
+      if (shutdownRequested())
+        return llvm::createStringError(
+            std::make_error_code(std::errc::operation_canceled),
+            "Got signal, shutting down");
       if (ferror(In))
         return llvm::errorCodeToError(
             std::error_code(errno, std::system_category()));
@@ -167,7 +173,7 @@
 }
 
 // Tries to read a line up to and including \n.
-// If failing, feof() or ferror() will be set.
+// If failing, feof(), ferror(), or shutdownRequested() will be set.
 bool readLine(std::FILE *In, std::string &Out) {
   static constexpr int BufSize = 1024;
   size_t Size = 0;
@@ -175,7 +181,8 @@
   for (;;) {
     Out.resize(Size + BufSize);
     // Handle EINTR which is sent when a debugger attaches on some platforms.
-    if (!llvm::sys::RetryAfterSignal(nullptr, ::fgets, &Out[Size], BufSize, In))
+    if (!retryAfterSignalUnlessShutdown(
+            nullptr, [&] { return std::fgets(&Out[Size], BufSize, In); }))
       return false;
     clearerr(In);
     // If the line contained null bytes, anything after it (including \n) will
@@ -190,7 +197,7 @@
 }
 
 // Returns None when:
-//  - ferror() or feof() are set.
+//  - ferror(), feof(), or shutdownRequested() are set.
 //  - Content-Length is missing or empty (protocol error)
 llvm::Optional<std::string> JSONTransport::readStandardMessage() {
   // A Language Server Protocol message starts with a set of HTTP headers,
@@ -244,8 +251,9 @@
   std::string JSON(ContentLength, '\0');
   for (size_t Pos = 0, Read; Pos < ContentLength; Pos += Read) {
     // Handle EINTR which is sent when a debugger attaches on some platforms.
-    Read = llvm::sys::RetryAfterSignal(0u, ::fread, &JSON[Pos], 1,
-                                       ContentLength - Pos, In);
+    Read = retryAfterSignalUnlessShutdown(0, [&]{
+      return std::fread(&JSON[Pos], 1, ContentLength - Pos, In);
+    });
     if (Read == 0) {
       elog("Input was aborted. Read only {0} bytes of expected {1}.", Pos,
            ContentLength);
@@ -263,7 +271,7 @@
 // - messages are delimited by '---' on a line by itself
 // - lines starting with # are ignored.
 // This is a testing path, so favor simplicity over performance here.
-// When returning None, feof() or ferror() will be set.
+// When returning None, feof(), ferror(), or shutdownRequested() will be set.
 llvm::Optional<std::string> JSONTransport::readDelimitedMessage() {
   std::string JSON;
   std::string Line;
@@ -280,6 +288,8 @@
     JSON += Line;
   }
 
+  if (shutdownRequested())
+    return llvm::None;
   if (ferror(In)) {
     elog("Input error while reading message!");
     return llvm::None;