1
#include "source/common/watchdog/abort_action.h"
2

            
3
#include "envoy/thread/thread.h"
4

            
5
#include "source/common/common/assert.h"
6
#include "source/common/common/fmt.h"
7
#include "source/common/common/logger.h"
8
#include "source/common/protobuf/utility.h"
9
#include "source/common/thread/terminate_thread.h"
10

            
11
namespace Envoy {
12
namespace Watchdog {
13
namespace {
14
constexpr uint64_t DefaultWaitDurationMs = 5000;
15
} // end namespace
16

            
17
AbortAction::AbortAction(envoy::watchdog::v3::AbortActionConfig& config,
18
                         Server::Configuration::GuardDogActionFactoryContext& /*context*/)
19
20
    : wait_duration_(absl::Milliseconds(
20
20
          PROTOBUF_GET_MS_OR_DEFAULT(config, wait_duration, DefaultWaitDurationMs))) {}
21

            
22
void AbortAction::run(
23
    envoy::config::bootstrap::v3::Watchdog::WatchdogAction::WatchdogEvent /*event*/,
24
    const std::vector<std::pair<Thread::ThreadId, MonotonicTime>>& thread_last_checkin_pairs,
25
1
    MonotonicTime /*now*/) {
26

            
27
1
  if (thread_last_checkin_pairs.empty()) {
28
1
    ENVOY_LOG_MISC(warn, "Watchdog AbortAction called without any thread.");
29
1
    return;
30
1
  }
31

            
32
  // The following lines of code won't be considered covered by code coverage
33
  // tools since they would run in DEATH tests.
34
  const auto& thread_id = thread_last_checkin_pairs[0].first;
35
  const std::string tid_string = thread_id.debugString();
36
  ENVOY_LOG_MISC(error, "Watchdog AbortAction terminating thread with tid {}.", tid_string);
37

            
38
  if (Thread::terminateThread(thread_id)) {
39
    // Successfully signaled to thread to terminate, sleep for wait_duration.
40
    absl::SleepFor(wait_duration_);
41
  } else {
42
    ENVOY_LOG_MISC(error, "Failed to terminate tid {}", tid_string);
43
  }
44

            
45
  // Abort from the action since the signaled thread hasn't yet crashed the process.
46
  // Panicing in the action gives flexibility since it doesn't depend on
47
  // external code to kill the process if the signal fails.
48
  PANIC(fmt::format(
49
      "Failed to terminate thread with id {}, aborting from Watchdog AbortAction instead.",
50
      tid_string));
51
}
52

            
53
} // namespace Watchdog
54
} // namespace Envoy