proxygen
StackTraceTest.cpp File Reference
#include <cstring>
#include <folly/experimental/TestUtil.h>
#include <folly/experimental/symbolizer/StackTrace.h>
#include <folly/experimental/symbolizer/Symbolizer.h>
#include <glog/logging.h>
#include <folly/portability/GTest.h>

Go to the source code of this file.

Functions

FOLLY_NOINLINE void foo1 ()
 
FOLLY_NOINLINE void foo2 ()
 
void verifyStackTraces ()
 
void handler (int, siginfo_t *, void *)
 
 TEST (StackTraceTest, Simple)
 
 TEST (StackTraceTest, Signal)
 
ssize_t read_all (int fd, uint8_t *buffer, size_t size)
 
off_t get_stack_trace (int fd, size_t file_pos, uint8_t *buffer, size_t count)
 
template<class StackTracePrinter >
void testStackTracePrinter (StackTracePrinter &printer, int fd)
 
 TEST (StackTraceTest, SafeStackTracePrinter)
 
 TEST (StackTraceTest, FastStackTracePrinter)
 

Variables

volatile bool handled = false
 

Function Documentation

void foo1 ( )

Definition at line 65 of file StackTraceTest.cpp.

References foo2().

Referenced by handler(), TEST(), and TEST_F().

65  {
66  foo2();
67 }
FOLLY_NOINLINE void foo2()
void foo2 ( )

Definition at line 69 of file StackTraceTest.cpp.

References verifyStackTraces().

Referenced by foo1(), free_function_retire_test(), TEST(), and TEST_F().

69  {
71 }
void verifyStackTraces()
off_t get_stack_trace ( int  fd,
size_t  file_pos,
uint8_t buffer,
size_t  count 
)

Definition at line 115 of file StackTraceTest.cpp.

References read_all().

Referenced by testStackTracePrinter().

115  {
116  off_t rv = lseek(fd, file_pos, SEEK_SET);
117  CHECK_EQ(rv, (off_t)file_pos);
118 
119  // Subtract 1 from size of buffer to hold nullptr.
120  ssize_t bytes_read = read_all(fd, buffer, count - 1);
121  CHECK_GT(bytes_read, 0);
122  buffer[bytes_read] = '\0';
123  return lseek(fd, 0, SEEK_CUR);
124 }
std::vector< uint8_t > buffer(kBufferSize+16)
int * count
ssize_t read_all(int fd, uint8_t *buffer, size_t size)
void handler ( int  ,
siginfo_t *  ,
void *   
)

Definition at line 74 of file StackTraceTest.cpp.

References foo1(), and handled.

Referenced by wangle::PipelineBase::addBack(), wangle::PipelineBase::addFront(), HTTPDownstreamTest< SPDY3_1CodecPair >::addSimpleNiceHandler(), HTTPDownstreamTest< SPDY3_1CodecPair >::addSimpleStrictHandler(), folly::allocate_unique(), folly::gen::detail::Interleave< Container >::Generator< Value, Source >::apply(), folly::gen::Group< Key, Value >::apply(), folly::gen::detail::Zip< Container >::Generator< Value1, Source, Value2, Result >::apply(), folly::gen::detail::ReferencedSource< Container, Value >::apply(), folly::gen::detail::Parallel< Ops >::Generator< Input, Source, InputDecayed, Composed, Output, OutputDecayed >::Puller::apply(), folly::gen::detail::PMap< Predicate >::Generator< Value, Source, Input, Output >::apply(), folly::gen::detail::CopiedSource< StorageType, Container >::apply(), folly::gen::detail::RangeSource< Iterator >::apply(), folly::gen::detail::Sequence< Value, SequenceImpl >::apply(), folly::gen::detail::Parallel< Ops >::Generator< Input, Source, InputDecayed, Composed, Output, OutputDecayed >::apply(), folly::gen::detail::Chain< Value, First, Second >::apply(), folly::gen::detail::ChunkedRangeSource< Iterator >::apply(), folly::gen::detail::Yield< Value, Source >::apply(), folly::gen::detail::SingleReference< Value >::apply(), folly::gen::detail::SingleCopy< Value >::apply(), folly::gen::detail::Map< Predicate >::Generator< Value, Source, Result >::apply(), folly::gen::detail::Filter< Predicate >::Generator< Value, Source >::apply(), folly::gen::detail::Until< Predicate >::Generator< Value, Source >::apply(), folly::gen::detail::Take::Generator< Value, Source >::apply(), folly::gen::detail::Visit< Visitor >::Generator< Value, Source >::apply(), folly::gen::detail::Stride::Generator< Value, Source >::apply(), folly::gen::detail::Sample< Random >::Generator< Value, Source, Rand, StorageType >::apply(), folly::gen::detail::Skip::Generator< Value, Source >::apply(), folly::gen::detail::Order< Selector, Comparer >::Generator< Value, Source, StorageType, Result >::apply(), folly::gen::detail::GroupBy< Selector >::Generator< Value, Source, ValueDecayed, Key, KeyDecayed >::apply(), folly::gen::detail::GroupByAdjacent< Selector >::Generator< Value, Source, ValueDecayed, Key, KeyDecayed >::apply(), folly::gen::detail::Distinct< Selector >::Generator< Value, Source >::apply(), folly::gen::detail::Batch::Generator< Value, Source, StorageType, VectorType >::apply(), folly::gen::detail::Window::Generator< Value, Source, StorageType >::apply(), folly::gen::detail::Concat::Generator< Inner, Source, InnerValue >::apply(), folly::gen::detail::RangeConcat::Generator< Range, Source, InnerValue >::apply(), folly::gen::detail::GuardImpl< Exception, ErrorHandler >::Generator< Value, Source >::apply(), folly::gen::detail::Dereference::Generator< Value, Source, Result >::apply(), folly::gen::detail::Indirect::Generator< Value, Source, Result >::apply(), folly::gen::detail::Cycle< forever >::Generator< Value, Source >::apply(), folly::gen::VirtualGen< Value >::WrapperImpl< Wrapped >::apply(), folly::gen::VirtualGen< Value >::apply(), folly::AsyncServerSocket::attachEventBase(), folly::AsyncServerSocket::backoffTimeoutExpired(), folly::AsyncServerSocket::detachEventBase(), TestAbortPost< stage >::doAbortTest(), folly::AsyncServerSocket::enterBackoff(), folly::LoggerDB::flushAllHandlers(), folly::LoggerDB::getConfigImpl(), folly::LogCategory::getDB(), wangle::BroadcastPool< T, R, P >::BroadcastManager::getHandler(), folly::AsyncServerSocket::getSockets(), wangle::PipelineBase::getTransport(), folly::gen::guard(), proxygen::HTTPSessionBase::handleErrorDirectly(), folly::LoggerDB::internalWarningImpl(), folly::AsyncSignalHandler::libeventCallback(), folly::EventHandler::libeventCallback(), folly::AsyncServerSocket::listen(), proxygen::MockHTTPTransaction::MockHTTPTransaction(), proxygen::RequestHandlerAdaptor::newExMessage(), proxygen::HTTPSession::newExTransaction(), wangle::ObservingPipelineFactory< std::string, std::string >::newPipeline(), wangle::MockObservingPipelineFactory::newPipeline(), proxygen::Filter::newPushedResponse(), proxygen::HTTPSession::newPushedTransaction(), proxygen::HTTPSession::numIncomingStreams(), proxygen::RequestHandlerAdaptor::onExTransaction(), HTTPUpstreamTest< SPDY3CodecPair >::openNiceTransaction(), HTTPUpstreamTest< SPDY3CodecPair >::openTransaction(), MockHTTPUpstreamTest::openTransaction(), folly::gen::operator|(), folly::AsyncServerSocket::pauseAccepting(), wangle::PipelineBase::remove(), folly::AsyncServerSocket::removeAcceptCallback(), wangle::PipelineBase::removeHelper(), proxygen::MockHTTPTransactionTransport::sendBody(), proxygen::HTTPTransaction::setHandler(), folly::AsyncServerSocket::setKeepAliveEnabled(), wangle::PipelineBase::setOwner(), proxygen::RequestHandler::setResponseHandler(), proxygen::Filter::setResponseHandler(), folly::AsyncServerSocket::setReusePortEnabled(), folly::AsyncServerSocket::setTosReflect(), EchoHandlerFixture::SetUp(), BroadcastHandlerTest::SetUp(), proxygen::HTTPDownstreamSession::setupOnHeadersComplete(), proxygen::ScopedHTTPServer::start(), folly::AsyncServerSocket::startAccepting(), folly::LoggerDB::startConfigUpdate(), wangle::StaticPipeline< R, W, Handler, Handlers... >::StaticPipeline(), folly::AsyncServerSocket::stopAccepting(), TEST(), TEST_F(), HTTPUpstreamTest< C >::testBasicRequest(), HTTPUpstreamTest< C >::testBasicRequestHttp10(), HTTPDownstreamTest< C >::testChunks(), MockCodecDownstreamTest::testGoaway(), testNumHandlers(), HTTPDownstreamTest< C >::testPriorities(), HTTPDownstreamTest< C >::testSimpleUpgrade(), HTTPUpstreamTest< C >::testSimpleUpgrade(), proxygen::HTTPSession::transactionTimeout(), TYPED_TEST_P(), proxygen::HTTPTransaction::Transport::~Transport(), and folly::gen::VirtualGen< Value >::WrapperBase::~WrapperBase().

74  {
75  // Yes, getStackTrace and VLOG aren't async-signal-safe, but signals
76  // raised with raise() aren't "async" signals.
77  foo1();
78  handled = true;
79 }
volatile bool handled
FOLLY_NOINLINE void foo1()
ssize_t read_all ( int  fd,
uint8_t buffer,
size_t  size 
)

Definition at line 95 of file StackTraceTest.cpp.

References buffer(), fizz::detail::read(), and uint8_t.

Referenced by get_stack_trace().

95  {
96  uint8_t* pos = buffer;
97  ssize_t bytes_read;
98  do {
99  bytes_read = read(fd, pos, size);
100  if (bytes_read < 0) {
101  if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
102  continue;
103  }
104  return bytes_read;
105  }
106 
107  pos += bytes_read;
108  size -= bytes_read;
109  } while (bytes_read > 0 && size > 0);
110 
111  return pos - buffer;
112 }
std::vector< uint8_t > buffer(kBufferSize+16)
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
size_t read(T &out, folly::io::Cursor &cursor)
Definition: Types-inl.h:258
TEST ( StackTraceTest  ,
Simple   
)

Definition at line 81 of file StackTraceTest.cpp.

References foo1().

81  {
82  foo1();
83 }
FOLLY_NOINLINE void foo1()
TEST ( StackTraceTest  ,
Signal   
)

Definition at line 85 of file StackTraceTest.cpp.

References EXPECT_TRUE, handled, and handler().

85  {
86  struct sigaction sa;
87  memset(&sa, 0, sizeof(sa));
88  sa.sa_sigaction = handler;
89  sa.sa_flags = SA_RESETHAND | SA_SIGINFO;
90  CHECK_ERR(sigaction(SIGUSR1, &sa, nullptr));
91  raise(SIGUSR1);
93 }
volatile bool handled
void handler(int, siginfo_t *, void *)
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( StackTraceTest  ,
SafeStackTracePrinter   
)

Definition at line 150 of file StackTraceTest.cpp.

References folly::test::TemporaryFile::fd().

150  {
151  test::TemporaryFile file;
152 
153  SafeStackTracePrinter printer{10, file.fd()};
154 
155  testStackTracePrinter<SafeStackTracePrinter>(printer, file.fd());
156 }
TEST ( StackTraceTest  ,
FastStackTracePrinter   
)

Definition at line 158 of file StackTraceTest.cpp.

References folly::test::TemporaryFile::fd().

158  {
159  test::TemporaryFile file;
160 
161  FastStackTracePrinter printer{
162  std::make_unique<FDSymbolizePrinter>(file.fd())};
163 
164  testStackTracePrinter<FastStackTracePrinter>(printer, file.fd());
165 }
template<class StackTracePrinter >
void testStackTracePrinter ( StackTracePrinter &  printer,
int  fd 
)

Definition at line 127 of file StackTraceTest.cpp.

References ASSERT_GT, ASSERT_STREQ, folly::gen::first, and get_stack_trace().

127  {
128  ASSERT_GT(fd, 0);
129 
130  printer.printStackTrace(true);
131  printer.flush();
132 
133  std::array<uint8_t, 4000> first;
134  off_t pos = get_stack_trace(fd, 0, first.data(), first.size());
135  ASSERT_GT(pos, 0);
136 
137  printer.printStackTrace(true);
138  printer.flush();
139 
140  std::array<uint8_t, 4000> second;
141  get_stack_trace(fd, pos, second.data(), second.size());
142 
143  // The first two lines refer to this stack frame, which is different in the
144  // two cases, so strip those off. The rest should be equal.
145  ASSERT_STREQ(
146  strchr(strchr((const char*)first.data(), '\n') + 1, '\n') + 1,
147  strchr(strchr((const char*)second.data(), '\n') + 1, '\n') + 1);
148 }
#define ASSERT_GT(val1, val2)
Definition: gtest.h:1976
#define ASSERT_STREQ(s1, s2)
Definition: gtest.h:2004
off_t get_stack_trace(int fd, size_t file_pos, uint8_t *buffer, size_t count)
constexpr detail::First first
Definition: Base-inl.h:2553
void verifyStackTraces ( )

Definition at line 33 of file StackTraceTest.cpp.

References folly::symbolizer::FrameArray< N >::addresses, folly::symbolizer::SymbolizePrinter::COLOR_IF_TTY, EXPECT_EQ, folly::symbolizer::FrameArray< N >::frameCount, folly::symbolizer::getStackTrace(), folly::symbolizer::getStackTraceSafe(), i, folly::INFO, folly::symbolizer::SymbolizePrinter::println(), and folly::symbolizer::Symbolizer::symbolize().

Referenced by foo2().

33  {
34  constexpr size_t kMaxAddresses = 100;
36  CHECK(getStackTrace(fa));
37 
39  CHECK(getStackTraceSafe(faSafe));
40 
41  CHECK_EQ(fa.frameCount, faSafe.frameCount);
42 
43  if (VLOG_IS_ON(1)) {
44  Symbolizer symbolizer;
45  OStreamSymbolizePrinter printer(std::cerr, SymbolizePrinter::COLOR_IF_TTY);
46 
47  symbolizer.symbolize(fa);
48  VLOG(1) << "getStackTrace\n";
49  printer.println(fa);
50 
51  symbolizer.symbolize(faSafe);
52  VLOG(1) << "getStackTraceSafe\n";
53  printer.println(faSafe);
54  }
55 
56  // Other than the top 2 frames (this one and getStackTrace /
57  // getStackTraceSafe), the stack traces should be identical
58  for (size_t i = 2; i < fa.frameCount; ++i) {
59  LOG(INFO) << "i=" << i << " " << std::hex << "0x" << fa.addresses[i]
60  << " 0x" << faSafe.addresses[i];
61  EXPECT_EQ(fa.addresses[i], faSafe.addresses[i]);
62  }
63 }
ssize_t getStackTraceSafe(uintptr_t *addresses, size_t maxAddresses)
Definition: StackTrace.cpp:53
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
ssize_t getStackTrace(uintptr_t *addresses, size_t maxAddresses)
Definition: StackTrace.cpp:25
void symbolize(const uintptr_t *addresses, SymbolizedFrame *frames, size_t frameCount)
Definition: Symbolizer.cpp:94

Variable Documentation