[PATCH] D93402: [clang-tidy] prevent readability-identifier-naming from triggering on implicit VarDecls in coroutines

2020-12-16 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf created this revision.
0x1eaf added reviewers: alexfh, njames93, aaron.ballman.
0x1eaf added projects: clang, clang-tools-extra.
Herald added subscribers: lxfind, modocache, xazax.hun.
0x1eaf requested review of this revision.
Herald added a subscriber: cfe-commits.

We have an internal bug report about readability-identifier-naming
warnings on implicit `__coro_gro` and `__promise` variables
in coroutines.

Turns out they haven't been marked as implicit in SemaCoroutine.
This diff resolves that and adds a couroutine test for the check.

Tested with:

> cd build/Debug/bin
> ./llvm-lit -sv --param build_mode=Debug \

  ../../tools/clang/tools/extra/test \
  --filter readability-identifier-naming.cpp


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D93402

Files:
  
clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-identifier-naming/system/coroutines.h
  clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
  clang/lib/Sema/SemaCoroutine.cpp

Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -544,6 +544,7 @@
   auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
  &PP.getIdentifierTable().get("__promise"), T,
  Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
+  VD->setImplicit(true);
   CheckVariableDeclarationType(VD);
   if (VD->isInvalidDecl())
 return nullptr;
@@ -1577,6 +1578,7 @@
   S.Context, &FD, FD.getLocation(), FD.getLocation(),
   &S.PP.getIdentifierTable().get("__coro_gro"), GroType,
   S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
+  GroDecl->setImplicit(true);
 
   S.CheckVariableDeclarationType(GroDecl);
   if (GroDecl->isInvalidDecl())
Index: clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
@@ -81,13 +81,14 @@
 // RUN: {key: readability-identifier-naming.LocalPointerPrefix, value: 'l_'}, \
 // RUN: {key: readability-identifier-naming.LocalConstantPointerCase, value: CamelCase}, \
 // RUN: {key: readability-identifier-naming.LocalConstantPointerPrefix, value: 'lc_'}, \
-// RUN:   ]}' -- -fno-delayed-template-parsing -Dbad_macro \
+// RUN:   ]}' -- -fno-delayed-template-parsing -Dbad_macro -std=c++17 -fcoroutines-ts \
 // RUN:   -I%S/Inputs/readability-identifier-naming \
 // RUN:   -isystem %S/Inputs/readability-identifier-naming/system
 
 // clang-format off
 
 #include 
+#include 
 #include "user-header.h"
 // NO warnings or fixes expected from declarations within header files without
 // the -header-filter= option
@@ -287,7 +288,7 @@
   // Overriding a badly-named base isn't a new violation.
   void BadBaseMethod() override {}
   // CHECK-FIXES: {{^}}  void v_Bad_Base_Method() override {}
-  
+
   void foo() {
 BadBaseMethod();
 // CHECK-FIXES: {{^}}v_Bad_Base_Method();
@@ -614,3 +615,14 @@
 auto GetRes(type_t& Param) -> decltype(Param.res());
 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for parameter 'Param'
 // CHECK-FIXES: auto GetRes(type_t& a_param) -> decltype(a_param.res());
+
+#pragma mark - Check implicit declarations in coroutines
+
+struct async_obj {
+public:
+  never_suspend operator co_await() const noexcept;
+};
+
+task ImplicitDeclTest(async_obj &a_object) {
+  co_await a_object;  // CHECK-MESSAGES-NOT: warning: invalid case style for local variable
+}
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-identifier-naming/system/coroutines.h
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-identifier-naming/system/coroutines.h
@@ -0,0 +1,34 @@
+#pragma once
+
+namespace std {
+namespace experimental {
+
+template 
+struct coroutine_traits {
+  using promise_type = typename ret_t::promise_type;
+};
+
+template 
+struct coroutine_handle {
+  static constexpr coroutine_handle from_address(void *addr) noexcept { return {}; };
+};
+
+} // namespace experimental
+} // namespace std
+
+struct never_suspend {
+  bool await_ready() noexcept { return false; }
+  template 
+  void await_suspend(coro_t handle) noexcept {}
+  void await_resume() noexcept {}
+};
+
+struct task {
+  struct promise_type {
+task get_return_object() noexcept { return {}; }
+never_suspend initial_suspend() noexcept { return {}; }
+never_suspend final_suspend() noexcept { return {}; }
+void return_void() {}
+void unhandled_exception() {}
+  };
+};
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/ma

[PATCH] D93402: [clang-tidy] prevent readability-identifier-naming from triggering on implicit VarDecls in coroutines

2020-12-16 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf updated this revision to Diff 312272.
0x1eaf added a comment.

Updated to address review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93402/new/

https://reviews.llvm.org/D93402

Files:
  
clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-identifier-naming/system/coroutines.h
  clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
  clang/lib/Sema/SemaCoroutine.cpp

Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -544,6 +544,7 @@
   auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(),
  &PP.getIdentifierTable().get("__promise"), T,
  Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
+  VD->setImplicit();
   CheckVariableDeclarationType(VD);
   if (VD->isInvalidDecl())
 return nullptr;
@@ -1577,6 +1578,7 @@
   S.Context, &FD, FD.getLocation(), FD.getLocation(),
   &S.PP.getIdentifierTable().get("__coro_gro"), GroType,
   S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
+  GroDecl->setImplicit();
 
   S.CheckVariableDeclarationType(GroDecl);
   if (GroDecl->isInvalidDecl())
Index: clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming.cpp
@@ -81,13 +81,14 @@
 // RUN: {key: readability-identifier-naming.LocalPointerPrefix, value: 'l_'}, \
 // RUN: {key: readability-identifier-naming.LocalConstantPointerCase, value: CamelCase}, \
 // RUN: {key: readability-identifier-naming.LocalConstantPointerPrefix, value: 'lc_'}, \
-// RUN:   ]}' -- -fno-delayed-template-parsing -Dbad_macro \
+// RUN:   ]}' -- -fno-delayed-template-parsing -Dbad_macro -std=c++17 -fcoroutines-ts \
 // RUN:   -I%S/Inputs/readability-identifier-naming \
 // RUN:   -isystem %S/Inputs/readability-identifier-naming/system
 
 // clang-format off
 
 #include 
+#include 
 #include "user-header.h"
 // NO warnings or fixes expected from declarations within header files without
 // the -header-filter= option
@@ -287,7 +288,7 @@
   // Overriding a badly-named base isn't a new violation.
   void BadBaseMethod() override {}
   // CHECK-FIXES: {{^}}  void v_Bad_Base_Method() override {}
-  
+
   void foo() {
 BadBaseMethod();
 // CHECK-FIXES: {{^}}v_Bad_Base_Method();
@@ -614,3 +615,14 @@
 auto GetRes(type_t& Param) -> decltype(Param.res());
 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: invalid case style for parameter 'Param'
 // CHECK-FIXES: auto GetRes(type_t& a_param) -> decltype(a_param.res());
+
+// Check implicit declarations in coroutines
+
+struct async_obj {
+public:
+  never_suspend operator co_await() const noexcept;
+};
+
+task ImplicitDeclTest(async_obj &a_object) {
+  co_await a_object;  // CHECK-MESSAGES-NOT: warning: invalid case style for local variable
+}
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-identifier-naming/system/coroutines.h
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-identifier-naming/system/coroutines.h
@@ -0,0 +1,34 @@
+#pragma once
+
+namespace std {
+namespace experimental {
+
+template 
+struct coroutine_traits {
+  using promise_type = typename ret_t::promise_type;
+};
+
+template 
+struct coroutine_handle {
+  static constexpr coroutine_handle from_address(void *addr) noexcept { return {}; };
+};
+
+} // namespace experimental
+} // namespace std
+
+struct never_suspend {
+  bool await_ready() noexcept { return false; }
+  template 
+  void await_suspend(coro_t handle) noexcept {}
+  void await_resume() noexcept {}
+};
+
+struct task {
+  struct promise_type {
+task get_return_object() noexcept { return {}; }
+never_suspend initial_suspend() noexcept { return {}; }
+never_suspend final_suspend() noexcept { return {}; }
+void return_void() {}
+void unhandled_exception() {}
+  };
+};
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D93402: [clang-tidy] prevent readability-identifier-naming from triggering on implicit VarDecls in coroutines

2020-12-16 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf added a comment.

> Do you need me to commit on your behalf?

Yes, I don't have commit access. The attribution line looks good to me. Thank 
you! 🙂


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93402/new/

https://reviews.llvm.org/D93402

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-10-26 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf added a comment.

I think this should work-around end-to-end test failure on Windows:

  diff --git a/clang-tools-extra/clangd/test/crash.test 
b/clang-tools-extra/clangd/test/crash.test
  index 1197e1ab07c3..68ef54808f09 100644
  --- a/clang-tools-extra/clangd/test/crash.test
  +++ b/clang-tools-extra/clangd/test/crash.test
  @@ -1,3 +1,4 @@
  +# REQUIRES: shell
   # Overflow the recursive json parser, prevent `yes` error due to broken pipe 
and `clangd` SIGSEGV from being treated as a failure.
   # RUN: (yes '[' || :) | head -n 5 | (clangd --input-style=delimited 2>&1 
|| :) | FileCheck %s
   #  CHECK: Signalled while processing message:

Alternatively, the test can be completely disabled for the time being.

I don't have commit access, should I create a new revision for review with the 
test change?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-10-08 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf updated this revision to Diff 378257.
0x1eaf added a comment.

Addressed feedback from the last round of comments. Sorry for the delay!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

Files:
  clang-tools-extra/clangd/JSONTransport.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/support/CMakeLists.txt
  clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
  clang-tools-extra/clangd/support/ThreadCrashReporter.h
  clang-tools-extra/clangd/test/crash.test
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp

Index: clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
@@ -0,0 +1,78 @@
+///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "support/ThreadCrashReporter.h"
+#include "support/Threading.h"
+#include "llvm/Support/Signals.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+static void infoSignalHandler() { ThreadCrashReporter::runCrashHandlers(); }
+
+TEST(ThreadCrashReporterTest, All) {
+#if defined(_WIN32)
+  // Simulate signals on Windows for unit testing purposes.
+  // The `crash.test` lit test checks the end-to-end integration.
+  auto SignalCurrentThread = []() { infoSignalHandler(); };
+#else
+  llvm::sys::SetInfoSignalFunction(&infoSignalHandler);
+  auto SignalCurrentThread = []() { raise(SIGUSR1); };
+#endif
+
+  AsyncTaskRunner Runner;
+  auto SignalAnotherThread = [&]() {
+Runner.runAsync("signal another thread", SignalCurrentThread);
+Runner.wait();
+  };
+
+  bool Called;
+  {
+ThreadCrashReporter ScopedReporter([&Called]() { Called = true; });
+// Check handler gets called when a signal gets delivered to the current
+// thread.
+Called = false;
+SignalCurrentThread();
+EXPECT_TRUE(Called);
+
+// Check handler does not get called when another thread gets signalled.
+Called = false;
+SignalAnotherThread();
+EXPECT_FALSE(Called);
+  }
+  // Check handler does not get called when the reporter object goes out of
+  // scope.
+  Called = false;
+  SignalCurrentThread();
+  EXPECT_FALSE(Called);
+
+  std::string Order = "";
+  {
+ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('a'); });
+{
+  ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('b'); });
+  SignalCurrentThread();
+}
+// Check that handlers are called in LIFO order.
+EXPECT_EQ(Order, "ba");
+
+// Check that current handler is the only one after the nested scope is
+// over.
+SignalCurrentThread();
+EXPECT_EQ(Order, "baa");
+  }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/clangd/unittests/CMakeLists.txt
===
--- clang-tools-extra/clangd/unittests/CMakeLists.txt
+++ clang-tools-extra/clangd/unittests/CMakeLists.txt
@@ -88,6 +88,7 @@
   TestIndex.cpp
   TestTU.cpp
   TestWorkspace.cpp
+  ThreadCrashReporterTests.cpp
   TidyProviderTests.cpp
   TypeHierarchyTests.cpp
   URITests.cpp
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -24,6 +24,7 @@
 #include "refactor/Rename.h"
 #include "support/Path.h"
 #include "support/Shutdown.h"
+#include "support/ThreadCrashReporter.h"
 #include "support/ThreadsafeFS.h"
 #include "support/Trace.h"
 #include "clang/Format/Format.h"
@@ -679,6 +680,8 @@
 
   llvm::InitializeAllTargetInfos();
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  llvm::sys::AddSignalHandler(
+  [](void *) { ThreadCrashReporter::runCrashHandlers(); }, nullptr);
   llvm::sys::SetInterruptFunction(&requestShutdown);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
 OS << versionString() << "\n"
Index: clang-tools-extra/clangd/test/crash.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/crash.test
@@ -0,0 +1,5 @@
+# Overflow the recursive json parser, prevent `yes` error due to broken pipe and `clangd` SIGSEGV from being treated as a failure.
+# RUN: (yes '[' || :) | head -n 5 | (clangd --input-style=delimited 2>&1 || :) | FileCheck %s
+#  CHECK: Sig

[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-10-08 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf marked 9 inline comments as done.
0x1eaf added a comment.

I've opted for simulating signals in the unit test on Windows by manually 
calling the signal handler, and added a list test to test the crash handling 
integration end-to-end.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-10-12 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf updated this revision to Diff 379124.
0x1eaf added a comment.

Updated the AST worker crash handler to avoid `std::string` copy: used a char 
pointer instead.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

Files:
  clang-tools-extra/clangd/JSONTransport.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/support/CMakeLists.txt
  clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
  clang-tools-extra/clangd/support/ThreadCrashReporter.h
  clang-tools-extra/clangd/test/crash.test
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp

Index: clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
@@ -0,0 +1,78 @@
+///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "support/ThreadCrashReporter.h"
+#include "support/Threading.h"
+#include "llvm/Support/Signals.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+static void infoSignalHandler() { ThreadCrashReporter::runCrashHandlers(); }
+
+TEST(ThreadCrashReporterTest, All) {
+#if defined(_WIN32)
+  // Simulate signals on Windows for unit testing purposes.
+  // The `crash.test` lit test checks the end-to-end integration.
+  auto SignalCurrentThread = []() { infoSignalHandler(); };
+#else
+  llvm::sys::SetInfoSignalFunction(&infoSignalHandler);
+  auto SignalCurrentThread = []() { raise(SIGUSR1); };
+#endif
+
+  AsyncTaskRunner Runner;
+  auto SignalAnotherThread = [&]() {
+Runner.runAsync("signal another thread", SignalCurrentThread);
+Runner.wait();
+  };
+
+  bool Called;
+  {
+ThreadCrashReporter ScopedReporter([&Called]() { Called = true; });
+// Check handler gets called when a signal gets delivered to the current
+// thread.
+Called = false;
+SignalCurrentThread();
+EXPECT_TRUE(Called);
+
+// Check handler does not get called when another thread gets signalled.
+Called = false;
+SignalAnotherThread();
+EXPECT_FALSE(Called);
+  }
+  // Check handler does not get called when the reporter object goes out of
+  // scope.
+  Called = false;
+  SignalCurrentThread();
+  EXPECT_FALSE(Called);
+
+  std::string Order = "";
+  {
+ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('a'); });
+{
+  ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('b'); });
+  SignalCurrentThread();
+}
+// Check that handlers are called in LIFO order.
+EXPECT_EQ(Order, "ba");
+
+// Check that current handler is the only one after the nested scope is
+// over.
+SignalCurrentThread();
+EXPECT_EQ(Order, "baa");
+  }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/clangd/unittests/CMakeLists.txt
===
--- clang-tools-extra/clangd/unittests/CMakeLists.txt
+++ clang-tools-extra/clangd/unittests/CMakeLists.txt
@@ -88,6 +88,7 @@
   TestIndex.cpp
   TestTU.cpp
   TestWorkspace.cpp
+  ThreadCrashReporterTests.cpp
   TidyProviderTests.cpp
   TypeHierarchyTests.cpp
   URITests.cpp
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -24,6 +24,7 @@
 #include "refactor/Rename.h"
 #include "support/Path.h"
 #include "support/Shutdown.h"
+#include "support/ThreadCrashReporter.h"
 #include "support/ThreadsafeFS.h"
 #include "support/Trace.h"
 #include "clang/Format/Format.h"
@@ -679,6 +680,8 @@
 
   llvm::InitializeAllTargetInfos();
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  llvm::sys::AddSignalHandler(
+  [](void *) { ThreadCrashReporter::runCrashHandlers(); }, nullptr);
   llvm::sys::SetInterruptFunction(&requestShutdown);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
 OS << versionString() << "\n"
Index: clang-tools-extra/clangd/test/crash.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/crash.test
@@ -0,0 +1,5 @@
+# Overflow the recursive json parser, prevent `yes` error due to broken pipe and `clangd` SIGSEGV from being treated as a failure.
+# RUN: (yes '[' || :) | head -n 5 | (clangd --input-style=delimited 2>&1 || :) | FileChec

[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-10-12 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf marked an inline comment as done.
0x1eaf added a comment.

I don't have commit access, so would appreciate if you commit it, thanks!

Forgot to mention on Friday:

I've instrumented preamble building, but haven't instrumented background 
indexing which is outside of `TUScheduler.cpp` and would require exposing 
`crashDump*` helpers and preferably moving them out of `TUScheduler.cpp`. And I 
think it might be easier to review it separately. Speaking of the helpers, 
where would you prefer those to be: a new file+header under clangd/support, or 
in some existing place?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-10-25 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf added a comment.

Are there any blockers to landing this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109506: [RFC] Print current request context along with the stack trance in clangd

2021-09-09 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf created this revision.
0x1eaf added reviewers: sammccall, ilya-biryukov, nridge.
0x1eaf added projects: clang, clang-tools-extra.
Herald added subscribers: usaxena95, kadircet, arphaman, javed.absar, mgorny.
0x1eaf requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.

Motivation:

At the moment it is hard to attribute a clangd crash to a specific request out 
of all in-flight requests that might be processed concurrently. So before we 
can act on production clangd crashes, we have to do quite some digging through 
the log tables populated by our in-house VSCode extension or sometimes even 
directly reach out to the affected developer. Having all the details needed to 
reproduce a crash printed alongside its stack trace has a potential to save us 
quite some time, that could better be spent on fixing the actual problems.

Implementation approach:

- introduce `ThreadSignalHandler` class that allows to set a temporary signal 
handler for the current thread
- follow RAII pattern to simplify printing context for crashes occurring within 
a particular scope
- hold `std::function` as a handler to allow capturing context to print
- set local `ThreadSignalHandler` within `JSONTransport::loop()` to print 
request JSON for main thread crashes, and in `ASTWorker::run()` to print the 
file paths, arguments and contents for worker thread crashes

`ThreadSignalHandler` currently allows only one active handler per thread, but 
the approach can be extended to support stacked handlers printing context 
incrementally.

Example output for main thread crashes:

  ...
  #15 0x7f7ddc819493 __libc_start_main (/lib64/libc.so.6+0x23493)
  #16 0x0249775e _start 
(/home/emmablink/local/llvm-project/build/bin/clangd+0x249775e)
  Signalled while processing message:
  {"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": 
{"textDocument": {"uri": "file:///home/emmablink/test.cpp", "languageId": 
"cpp", "version": 1, "text": "template \nclass Bar {\n  Bar 
*variables_to_modify;\n  foo() {\nfor (auto *c : *variables_to_modify)\n
  delete c;\n  }\n};\n"}}}


Example output for AST worker crashes:

  ...
  #41 0x7fb18304c14a start_thread pthread_create.c:0:0
  #42 0x7fb181bfcdc3 clone (/lib64/libc.so.6+0xfcdc3)
  Signalled during AST action:
  Filename: test.cpp
  Directory: /home/emmablink
  Command Line: /usr/bin/clang 
-resource-dir=/data/users/emmablink/llvm-project/build/lib/clang/14.0.0 -- 
/home/emmablink/test.cpp
  Version: 1
  Contents:
  template 
  class Bar {
Bar *variables_to_modify;
foo() {
  for (auto *c : *variables_to_modify)
delete c;
}
  };


Testing:

I’m not sure what is the best way to automatically test signal handling and 
would welcome suggestions. One way could be to introduce a unit test that would 
set up a `ThreadSignalHandler` and just signal itself. Another way might be to 
set up a lit test that would spawn clangd, send a message to it, signal it 
immediately and check the standard output, although this might be prone to race 
conditions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D109506

Files:
  clang-tools-extra/clangd/JSONTransport.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/support/CMakeLists.txt
  clang-tools-extra/clangd/support/ThreadSignalHandler.cpp
  clang-tools-extra/clangd/support/ThreadSignalHandler.h

Index: clang-tools-extra/clangd/support/ThreadSignalHandler.h
===
--- /dev/null
+++ clang-tools-extra/clangd/support/ThreadSignalHandler.h
@@ -0,0 +1,31 @@
+//===--- ThreadSignalHandler.h - Thread local signal handling *- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include 
+
+namespace clang {
+namespace clangd {
+
+using ThreadSignalHandlerCallback = std::function;
+
+class ThreadSignalHandler {
+public:
+  ThreadSignalHandler(const ThreadSignalHandlerCallback &ThreadLocalCallback);
+  ~ThreadSignalHandler();
+
+  ThreadSignalHandler(ThreadSignalHandler &&);
+  ThreadSignalHandler(const ThreadSignalHandler &) = delete;
+  ThreadSignalHandler &operator=(ThreadSignalHandler &&) = delete;
+  ThreadSignalHandler &operator=(const ThreadSignalHandler &) = delete;
+
+private:
+  ThreadSignalHandlerCallback Callback;
+};
+
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/clangd/support/ThreadSignalHandler.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/support/ThreadSignalHandler.cpp
@@ -0,0 +1,50 @@
+//===--- ThreadSignalHandler.cpp - Thread local signal handling --*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License 

[PATCH] D109506: [RFC] Print current request context along with the stack trance in clangd

2021-09-10 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf added a comment.

Thank you for such a prompt and thorough review!

Please consider all the comments I haven't replied to acknowledged and I'm 
going to resolve the issues with the next update.




Comment at: clang-tools-extra/clangd/JSONTransport.cpp:117
+  OS << "Signalled while processing message:\n";
+  OS << JSON << "\r\n";
+});

sammccall wrote:
> why \r?
the message itself is terminated with `\r\n` in the protocol and I just 
mimicked it for no good reason — will correct



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:1381
+  auto &OS = llvm::errs();
+  OS << "Signalled during AST action:\n";
+  auto &Command = FileInputs.CompileCommand;

sammccall wrote:
> the name of the action is available as CurrentRequest->Action, which I think 
> is safe to either pass into this function or read directly here.
I've noticed the the action name is always hardcoded as “Build AST ({version})” 
and just logged the version directly below, but I guess it's not forward 
compatible, so I'm going to log both…



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:1392
+  OS << "Contents:\n";
+  OS << FileInputs.Contents << "\n";
+}

sammccall wrote:
> sammccall wrote:
> > hmm, this is potentially really useful (could gather full reproducers) but 
> > also is going to dominate the output and make it annoying to see the stack 
> > traces/other details. I'm worried this may make this feature net-negative 
> > for a majority of users, who won't find the right parts of the output to 
> > report...
> > 
> > How critical do you think this is for debugging crashes in practice? (I 
> > suspect fairly important!)
> > Since we're taking liberties with async-signal-safety anyway, it might be 
> > possible to get this sent to a tempfile, which might be more useful. In any 
> > case, we might want full file dumps to be off by default outside of 
> > environments where anyone is likely to actually try to get the reproducers.
> > 
> > I'd probably suggest leaving this out of the initial patch entirely so we 
> > can focus on getting the rest of the mechanism right.
> another thought along the lines of reproducers (but nothing for this patch)...
> 
> If we're working on a file and have a preamble, then the headers that make up 
> the preamble are relevant. In practice it's hard to reproduce bug reports we 
> get because we need all their headers. If we're using a preamble then just 
> dumping all the filenames it includes would make it possible for some tool to 
> take the crash report and zip up a reproducer.
> 
> (This probably needs the ability to run all of the handlers for the current 
> thread, not just the top of the stack, since we acquire the relevant preamble 
> later)
> How critical do you think this is for debugging crashes in practice?

For us it would likely be of utmost importance as our VSCode extension routes 
requests to [Glean](https://glean.software) until local clangd finishes the 
compilation, so clangd ends up mostly being used for modified files, and the 
crashes might be unreproducible on the original source…

> I'd probably suggest leaving this out of the initial patch entirely so we can 
> focus on getting the rest of the mechanism right.

Alright, will remove the file contents with the next update.

> In any case, we might want full file dumps to be off by default outside of 
> environments where anyone is likely to actually try to get the reproducers.

What would be the best way to re-add it in a subsequent revision: make it 
configurable via a command line option, or via an environment variable? And if 
it's just an env var, maybe we could include it conditionally in this revision?

> If we're using a preamble then just dumping all the filenames it includes 
> would make it possible for some tool to take the crash report and zip up a 
> reproducer.

We had discussions within the team about potentially implementing a similar 
tool, but the rough idea was to rely on VCS to collect the changes as the delta 
would normally be smaller than bundling all the headers that the TU includes. 
But if the VCS-agnostic approach would be simpler and more portable — I'm all 
for it :)



Comment at: clang-tools-extra/clangd/support/ThreadSignalHandler.cpp:15
+
+static llvm::sys::ThreadLocal CurrentCallback;
+

sammccall wrote:
> sammccall wrote:
> > sammccall wrote:
> > > we assume `thread_local` in clangd (see support/Context.ccp)
> > > 
> > > It's possible that llvm::sys::ThreadLocal happens to play nicer with 
> > > signal handlers in practice (none of these are completely safe!), but 
> > > unless we've seen some concrete evidence I'd rather just have `static 
> > > thread_local ThreadSignalHandlerCallback*` here
> > we can quite easily support a stack of handlers, such that we dump *all* 
> > living handlers on the crashing thread.
> > 
> > just give e

[PATCH] D109506: [RFC] Print current request context along with the stack trance in clangd

2021-09-10 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf added inline comments.



Comment at: clang-tools-extra/clangd/support/ThreadSignalHandler.cpp:22
+  ThreadSignalHandlerCallback *Callback = CurrentCallback.get();
+  // TODO: ignore non thread local signals like SIGTERM
+  if (Callback) {

sammccall wrote:
> I think we should do this already, probably just starting with an allowlist 
> of `SIGBUS, SIGFPE, SIGILL, SIGSEGV` (these are signals that are delivered to 
> the thread that triggered them per the linux docs).
> 
> I'm also wondering how portable this assumption/mechanism is, e.g. whether we 
> should enable it for certain platforms only. I guess it's probably true for 
> unixy things, and apparently mostly true for windows too[1]? I'm a little 
> concerned *something* may go wrong on windows, though.
> 
> [1] 
> https://stackoverflow.com/questions/15879342/which-thread-are-signal-handlers-e-g-signalsigint-crtl-c-called-on
I've just looked into adding filtering by signal number and there doesn't seem 
to be a way to do this portably in LLVM. But it looks like it might be safe 
enough to skip the filtering at all:
* From a cursory look at Windows `Signals.inc` it looks like the “signal” 
handling is implemented via 
[SetUnhandledExceptionFilter()](https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter)
 which is thread-directed, and the `SetConsoleCtrlHandler()` callback [does not 
call](https://reviews.llvm.org/source/llvm-github/browse/main/llvm/lib/Support/Windows/Signals.inc$843-846)
 the registered handlers.
* And on Unix platforms the `AddSignalHandler()` callbacks are called 
[only](https://reviews.llvm.org/source/llvm-github/browse/main/llvm/include/llvm/Support/Signals.h$62-64)
 for 
[KillSigs](https://reviews.llvm.org/source/llvm-github/browse/main/llvm/lib/Support/Unix/Signals.inc$217)
 out of which only `SIGQUIT` seem to be process-directed and would be delivered 
to [any thread](https://man7.org/linux/man-pages/man7/signal.7.html) that is 
not blocking it, but if the thread gets delivered to has a 
`ThreadCrashReporter` installed during the interrupt — it seems to make sense 
to run the handler and let it print the thread-local context information (at 
least there seems to be no harm in doing so).

What do you think?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109772: [clangd] Print current request context along with the stack trace

2021-09-14 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf created this revision.
0x1eaf added reviewers: sammccall, ilya-biryukov, nridge.
0x1eaf added projects: clang, clang-tools-extra.
Herald added subscribers: usaxena95, kadircet, arphaman, javed.absar, mgorny.
0x1eaf requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.

Motivation:

At the moment it is hard to attribute a clangd crash to a specific request out 
of all in-flight requests that might be processed concurrently. So before we 
can act on production clangd crashes, we have to do quite some digging through 
the log tables populated by our in-house VSCode extension or sometimes even 
directly reach out to the affected developer. Having all the details needed to 
reproduce a crash printed alongside its stack trace has a potential to save us 
quite some time, that could better be spent on fixing the actual problems.

Implementation approach:

- introduce `ThreadCrashReporter` class that allows to set a temporary signal 
handler for the current thread
- follow RAII pattern to simplify printing context for crashes occurring within 
a particular scope
- hold `std::function` as a handler to allow capturing context to print
- set local `ThreadCrashReporter` within `JSONTransport::loop()` to print 
request JSON for main thread crashes, and in `ASTWorker::run()` to print the 
file paths, arguments and contents for worker thread crashes

`ThreadCrashReporter` currently allows only one active handler per thread, but 
the approach can be extended to support stacked handlers printing context 
incrementally.

Example output for main thread crashes:

  ...
  #15 0x7f7ddc819493 __libc_start_main (/lib64/libc.so.6+0x23493)
  #16 0x0249775e _start 
(/home/emmablink/local/llvm-project/build/bin/clangd+0x249775e)
  Signalled while processing message:
  {"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": 
{"textDocument": {"uri": "file:///home/emmablink/test.cpp", "languageId": 
"cpp", "version": 1, "text": "template \nclass Bar {\n  Bar 
*variables_to_modify;\n  foo() {\nfor (auto *c : *variables_to_modify)\n
  delete c;\n  }\n};\n"}}}


Example output for AST worker crashes:

  ...
  #41 0x7fb18304c14a start_thread pthread_create.c:0:0
  #42 0x7fb181bfcdc3 clone (/lib64/libc.so.6+0xfcdc3)
  Signalled during AST action:
  Filename: test.cpp
  Directory: /home/emmablink
  Command Line: /usr/bin/clang 
-resource-dir=/data/users/emmablink/llvm-project/build/lib/clang/14.0.0 -- 
/home/emmablink/test.cpp
  Version: 1
  Contents:
  template 
  class Bar {
Bar *variables_to_modify;
foo() {
  for (auto *c : *variables_to_modify)
delete c;
}
  };


Testing:

The unit test covers the thread-localitity and nesting aspects of 
`ThreadCrashReporter`. There might be way to set up a lit-based integration 
test that would spawn clangd, send a message to it, signal it immediately and 
check the standard output, but this might be prone to raceconditions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D109772

Files:
  clang-tools-extra/clangd/JSONTransport.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/support/CMakeLists.txt
  clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
  clang-tools-extra/clangd/support/ThreadCrashReporter.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp

Index: clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
@@ -0,0 +1,71 @@
+///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "support/ThreadCrashReporter.h"
+#include "support/Threading.h"
+#include "llvm/Support/Signals.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+static void infoHandler() { ThreadCrashReporter::runCrashHandlers(nullptr); }
+
+TEST(ThreadCrashReporterTest, All) {
+  llvm::sys::SetInfoSignalFunction(&infoHandler);
+  AsyncTaskRunner Runner;
+  auto SignalCurrentThread = []() { raise(SIGUSR1); };
+  auto SignalAnotherThread = [&]() {
+Runner.runAsync("signal another thread", SignalCurrentThread);
+Runner.wait();
+  };
+
+  bool Called;
+  {
+ThreadCrashReporter ScopedReporter([&Called]() { Called = true; });
+// Check handler gets called when a signal gets delivered to the current
+// thread.
+Called = false;
+SignalCurrentThread();
+EXPECT_TRUE(Called);
+
+// Check handler does not get call

[PATCH] D109506: [RFC] Print current request context along with the stack trance in clangd

2021-09-14 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf updated this revision to Diff 372510.
0x1eaf added a comment.

addressed review comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

Files:
  clang-tools-extra/clangd/JSONTransport.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/support/CMakeLists.txt
  clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
  clang-tools-extra/clangd/support/ThreadCrashReporter.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp

Index: clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
@@ -0,0 +1,71 @@
+///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "support/ThreadCrashReporter.h"
+#include "support/Threading.h"
+#include "llvm/Support/Signals.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+static void infoHandler() { ThreadCrashReporter::runCrashHandlers(nullptr); }
+
+TEST(ThreadCrashReporterTest, All) {
+  llvm::sys::SetInfoSignalFunction(&infoHandler);
+  AsyncTaskRunner Runner;
+  auto SignalCurrentThread = []() { raise(SIGUSR1); };
+  auto SignalAnotherThread = [&]() {
+Runner.runAsync("signal another thread", SignalCurrentThread);
+Runner.wait();
+  };
+
+  bool Called;
+  {
+ThreadCrashReporter ScopedReporter([&Called]() { Called = true; });
+// Check handler gets called when a signal gets delivered to the current
+// thread.
+Called = false;
+SignalCurrentThread();
+EXPECT_TRUE(Called);
+
+// Check handler does not get called when another thread gets signalled.
+Called = false;
+SignalAnotherThread();
+EXPECT_FALSE(Called);
+  }
+  // Check handler does not get called when the reporter object goes out of
+  // scope.
+  Called = false;
+  SignalCurrentThread();
+  EXPECT_FALSE(Called);
+
+  std::string Order = "";
+  {
+ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('a'); });
+{
+  ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('b'); });
+  SignalCurrentThread();
+}
+// Check that handlers are called in FIFO order.
+EXPECT_EQ(Order, "ab");
+
+// Check that current handler is the only one after the nested scope is
+// over.
+SignalCurrentThread();
+EXPECT_EQ(Order, "aba");
+  }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/clangd/unittests/CMakeLists.txt
===
--- clang-tools-extra/clangd/unittests/CMakeLists.txt
+++ clang-tools-extra/clangd/unittests/CMakeLists.txt
@@ -88,6 +88,7 @@
   TestIndex.cpp
   TestTU.cpp
   TestWorkspace.cpp
+  ThreadCrashReporterTests.cpp
   TidyProviderTests.cpp
   TypeHierarchyTests.cpp
   URITests.cpp
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -24,6 +24,7 @@
 #include "refactor/Rename.h"
 #include "support/Path.h"
 #include "support/Shutdown.h"
+#include "support/ThreadCrashReporter.h"
 #include "support/ThreadsafeFS.h"
 #include "support/Trace.h"
 #include "clang/Format/Format.h"
@@ -679,6 +680,7 @@
 
   llvm::InitializeAllTargetInfos();
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  llvm::sys::AddSignalHandler(&ThreadCrashReporter::runCrashHandlers, nullptr);
   llvm::sys::SetInterruptFunction(&requestShutdown);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
 OS << versionString() << "\n"
Index: clang-tools-extra/clangd/support/ThreadCrashReporter.h
===
--- /dev/null
+++ clang-tools-extra/clangd/support/ThreadCrashReporter.h
@@ -0,0 +1,48 @@
+//===--- ThreadCrashReporter.h - Thread local signal handling *- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREAD_CRASH_REPORTER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREAD_CRASH_REPORTER_H
+
+#include 
+
+namespace clang {
+namespace cl

[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-09-14 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf updated this revision to Diff 372515.
0x1eaf retitled this revision from "[RFC] Print current request context along 
with the stack trance in clangd" to "[clangd] Print current request context 
along with the stack trace".
0x1eaf edited the summary of this revision.
0x1eaf added a comment.

updated revision description for final review after renaming the class


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

Files:
  clang-tools-extra/clangd/JSONTransport.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/support/CMakeLists.txt
  clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
  clang-tools-extra/clangd/support/ThreadCrashReporter.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp

Index: clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
@@ -0,0 +1,71 @@
+///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "support/ThreadCrashReporter.h"
+#include "support/Threading.h"
+#include "llvm/Support/Signals.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+
+namespace {
+
+static void infoHandler() { ThreadCrashReporter::runCrashHandlers(nullptr); }
+
+TEST(ThreadCrashReporterTest, All) {
+  llvm::sys::SetInfoSignalFunction(&infoHandler);
+  AsyncTaskRunner Runner;
+  auto SignalCurrentThread = []() { raise(SIGUSR1); };
+  auto SignalAnotherThread = [&]() {
+Runner.runAsync("signal another thread", SignalCurrentThread);
+Runner.wait();
+  };
+
+  bool Called;
+  {
+ThreadCrashReporter ScopedReporter([&Called]() { Called = true; });
+// Check handler gets called when a signal gets delivered to the current
+// thread.
+Called = false;
+SignalCurrentThread();
+EXPECT_TRUE(Called);
+
+// Check handler does not get called when another thread gets signalled.
+Called = false;
+SignalAnotherThread();
+EXPECT_FALSE(Called);
+  }
+  // Check handler does not get called when the reporter object goes out of
+  // scope.
+  Called = false;
+  SignalCurrentThread();
+  EXPECT_FALSE(Called);
+
+  std::string Order = "";
+  {
+ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('a'); });
+{
+  ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('b'); });
+  SignalCurrentThread();
+}
+// Check that handlers are called in FIFO order.
+EXPECT_EQ(Order, "ab");
+
+// Check that current handler is the only one after the nested scope is
+// over.
+SignalCurrentThread();
+EXPECT_EQ(Order, "aba");
+  }
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/clangd/unittests/CMakeLists.txt
===
--- clang-tools-extra/clangd/unittests/CMakeLists.txt
+++ clang-tools-extra/clangd/unittests/CMakeLists.txt
@@ -88,6 +88,7 @@
   TestIndex.cpp
   TestTU.cpp
   TestWorkspace.cpp
+  ThreadCrashReporterTests.cpp
   TidyProviderTests.cpp
   TypeHierarchyTests.cpp
   URITests.cpp
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -24,6 +24,7 @@
 #include "refactor/Rename.h"
 #include "support/Path.h"
 #include "support/Shutdown.h"
+#include "support/ThreadCrashReporter.h"
 #include "support/ThreadsafeFS.h"
 #include "support/Trace.h"
 #include "clang/Format/Format.h"
@@ -679,6 +680,7 @@
 
   llvm::InitializeAllTargetInfos();
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  llvm::sys::AddSignalHandler(&ThreadCrashReporter::runCrashHandlers, nullptr);
   llvm::sys::SetInterruptFunction(&requestShutdown);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) {
 OS << versionString() << "\n"
Index: clang-tools-extra/clangd/support/ThreadCrashReporter.h
===
--- /dev/null
+++ clang-tools-extra/clangd/support/ThreadCrashReporter.h
@@ -0,0 +1,48 @@
+//===--- ThreadCrashReporter.h - Thread local signal handling *- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//

[PATCH] D109506: [clangd] Print current request context along with the stack trace

2021-09-14 Thread Emma Blink via Phabricator via cfe-commits
0x1eaf added a comment.

I've tried making an integration test in addition to the unit test, but I 
couldn't find a way to make lit ignore the crashed process exit status:

  FAIL: Clangd :: crash.test (1049 of 1049)
   TEST 'Clangd :: crash.test' FAILED 
  Script:
  --
  : 'RUN: at line 2';   yes '[' | head -n 5 | sh -c "clangd 
--input-style=delimited 2>&1 || true"
  --
  Exit Code: 141

I've also tried using `not` to the same effect:

  # RUN: yes '[' | head -n 5 | not clangd --input-style=delimited

Is there some trick that I'm missing?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109506/new/

https://reviews.llvm.org/D109506

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits