You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2017/03/14 18:58:08 UTC

[1/2] mesos git commit: Windows: Added Glog patch for enabling stack trace.

Repository: mesos
Updated Branches:
  refs/heads/master cd40c419a -> 5d3908a4c


Windows: Added Glog patch for enabling stack trace.

This relies on an updated `glog-da816ea70.tar.gz` tarball
in the Mesos 3rdparty repository, which is itself generated from
the `da816ea70` commit on github.com/google/glog.

Additionally, this applies a patch that includes stacktrace support
to glog on Windows.  The code in this patch is included in an upstream
pull request:
https://github.com/google/glog/pull/168

If and when that pull request gets merged, we will update the glog
tarball and remove the need for the extra patch file.

Review: https://reviews.apache.org/r/57490/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/ef3ebf3f
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/ef3ebf3f
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/ef3ebf3f

Branch: refs/heads/master
Commit: ef3ebf3fda475ac0d8d51d12ba5c2e10cb0607df
Parents: cd40c41
Author: Andrew Schwartzmeyer <an...@schwartzmeyer.com>
Authored: Mon Mar 13 18:06:11 2017 -0700
Committer: Joseph Wu <jo...@apache.org>
Committed: Tue Mar 14 10:25:33 2017 -0700

----------------------------------------------------------------------
 3rdparty/CMakeLists.txt       |   3 +-
 3rdparty/glog-da816ea70.patch | 726 +++++++++++++++++++++++++++++++++++++
 2 files changed, 728 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/ef3ebf3f/3rdparty/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt
index bb5f713..bb61ef0 100755
--- a/3rdparty/CMakeLists.txt
+++ b/3rdparty/CMakeLists.txt
@@ -60,7 +60,7 @@ if (WIN32)
   # (as well as all the other third-party dependencies) on MSVC 1900.
   #
   # [1] https://github.com/google/glog/pull/43
-  set(GLOG_URL   ${UPSTREAM_URL}/glog-v0.3.4-g4d391fe.tar.gz)
+  set(GLOG_URL   ${UPSTREAM_URL}/glog-da816ea70.tar.gz)
   set(CURL_URL   ${UPSTREAM_URL}/curl-${CURL_VERSION}.tar.gz)
   set(LIBAPR_URL ${UPSTREAM_URL}/libapr-${LIBAPR_VERSION}.tar.gz)
   set(ZLIB_URL   ${UPSTREAM_URL}/zlib-${ZLIB_VERSION}.tar.gz)
@@ -107,6 +107,7 @@ if (NOT WIN32)
   set(LIBEVENT_INSTALL_CMD mkdir -p ${LIBEVENT_LIB_ROOT} && cp -r ${LIBEVENT_ROOT}-build/lib/. ${LIBEVENT_LIB_DIR} && cp -r ${LIBEVENT_ROOT}-build/include/. ${LIBEVENT_INCLUDE_DIR} && cp -r ${LIBEVENT_ROOT}/include/. ${LIBEVENT_INCLUDE_DIR})
 elseif (WIN32)
   set(GLOG_INSTALL_CMD ${CMAKE_NOOP})
+  set(GLOG_PATCH_CMD ${PATCHEXE_LOCATION} -p1 < ${MESOS_3RDPARTY_SRC}/glog-da816ea70.patch)
 
   set(LIBEVENT_INSTALL_CMD ${CMAKE_NOOP})
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/ef3ebf3f/3rdparty/glog-da816ea70.patch
----------------------------------------------------------------------
diff --git a/3rdparty/glog-da816ea70.patch b/3rdparty/glog-da816ea70.patch
new file mode 100644
index 0000000..2f0fae3
--- /dev/null
+++ b/3rdparty/glog-da816ea70.patch
@@ -0,0 +1,726 @@
+diff --git c/CMakeLists.txt w/CMakeLists.txt
+index 7ede6e7ad..1b05456e4 100644
+--- c/CMakeLists.txt
++++ w/CMakeLists.txt
+@@ -364,9 +364,9 @@ set (GLOG_SRCS
+   src/vlog_is_on.cc
+ )
+
+-if (HAVE_PTHREAD)
++if (HAVE_PTHREAD OR WIN32)
+   list (APPEND GLOG_SRCS src/signalhandler.cc)
+-endif (HAVE_PTHREAD)
++endif (HAVE_PTHREAD OR WIN32)
+
+ if (WIN32)
+   list (APPEND GLOG_SRCS
+@@ -455,6 +455,12 @@ if (HAVE_EXECINFO_H)
+   set (HAVE_STACKTRACE 1)
+ endif (HAVE_EXECINFO_H)
+
++if (WIN32)
++  set (HAVE_STACKTRACE 1)
++  set (HAVE_SYMBOLIZE 1)
++  target_link_libraries (glog PUBLIC Dbghelp.lib)
++endif (WIN32)
++
+ if (UNIX OR (APPLE AND HAVE_DLADDR))
+   set (HAVE_SYMBOLIZE 1)
+ endif (UNIX OR (APPLE AND HAVE_DLADDR))
+@@ -527,13 +533,13 @@ if (BUILD_TESTING)
+
+   target_link_libraries (utilities_unittest PRIVATE glog)
+
+-  if (HAVE_STACKTRACE AND HAVE_SYMBOLIZE)
++  if (HAVE_STACKTRACE AND HAVE_SYMBOLIZE AND NOT WIN32)
+     add_executable (signalhandler_unittest
+       src/signalhandler_unittest.cc
+     )
+
+     target_link_libraries (signalhandler_unittest PRIVATE glog)
+-  endif (HAVE_STACKTRACE AND HAVE_SYMBOLIZE)
++  endif (HAVE_STACKTRACE AND HAVE_SYMBOLIZE AND NOT WIN32)
+
+   add_test (NAME demangle COMMAND demangle_unittest)
+   add_test (NAME logging COMMAND logging_unittest)
+diff --git c/src/demangle.cc w/src/demangle.cc
+index e858181a6..cf897457a 100644
+--- c/src/demangle.cc
++++ w/src/demangle.cc
+@@ -35,10 +35,16 @@
+ // Note that we only have partial C++0x support yet.
+
+ #include <stdio.h>  // for NULL
++#include "utilities.h"
+ #include "demangle.h"
+
++#if defined(OS_WINDOWS)
++#include <Dbghelp.h>
++#endif
++
+ _START_GOOGLE_NAMESPACE_
+
++#if !defined(OS_WINDOWS)
+ typedef struct {
+   const char *abbrev;
+   const char *real_name;
+@@ -1293,12 +1299,32 @@ static bool ParseTopLevelMangledName(State *state) {
+   }
+   return false;
+ }
++#endif
+
+ // The demangler entry point.
+ bool Demangle(const char *mangled, char *out, int out_size) {
++#if defined(OS_WINDOWS)
++  // When built with incremental linking, the Windows debugger
++  // library provides a more complicated `Symbol->Name` with the
++  // Incremental Linking Table offset, which looks like
++  // `@ILT+1105(?func@Foo@@SAXH@Z)`. However, the demangler expects
++  // only the mangled symbol, `?func@Foo@@SAXH@Z`. Fortunately, the
++  // mangled symbol is guaranteed not to have parentheses,
++  // so we search for `(` and extract up to `)`.
++  std::string symbol(mangled);
++  size_t mark = symbol.find('(');
++  if (mark != std::string::npos) {
++    // Extract the string `(?...)`
++    std::string temp = symbol.substr(mark);
++    // Remove the surrounding parentheses
++    symbol = temp.substr(1, temp.size() - 2);
++  } // Else the symbol wasn't inside a set of parentheses
++  return UnDecorateSymbolName(symbol.c_str(), out, out_size, UNDNAME_COMPLETE);
++#else
+   State state;
+   InitState(&state, mangled, out, out_size);
+   return ParseTopLevelMangledName(&state) && !state.overflowed;
++#endif
+ }
+
+ _END_GOOGLE_NAMESPACE_
+diff --git c/src/demangle_unittest.cc w/src/demangle_unittest.cc
+index 32f322101..be483411f 100644
+--- c/src/demangle_unittest.cc
++++ w/src/demangle_unittest.cc
+@@ -62,18 +62,37 @@ static const char *DemangleIt(const char * const mangled) {
+   }
+ }
+
++#if defined(OS_WINDOWS)
++
++TEST(Demangle, Windows) {
++  EXPECT_STREQ(
++    "public: static void __cdecl Foo::func(int)",
++    DemangleIt("?func@Foo@@SAXH@Z"));
++  EXPECT_STREQ(
++    "public: static void __cdecl Foo::func(int)",
++    DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)"));
++  EXPECT_STREQ(
++    "int __cdecl foobarArray(int * const)",
++    DemangleIt("?foobarArray@@YAHQAH@Z"));
++}
++
++#else
++
+ // Test corner cases of bounary conditions.
+ TEST(Demangle, CornerCases) {
+-  char tmp[10];
+-  EXPECT_TRUE(Demangle("_Z6foobarv", tmp, sizeof(tmp)));
+-  // sizeof("foobar()") == 9
+-  EXPECT_STREQ("foobar()", tmp);
+-  EXPECT_TRUE(Demangle("_Z6foobarv", tmp, 9));
+-  EXPECT_STREQ("foobar()", tmp);
+-  EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 8));  // Not enough.
+-  EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 1));
+-  EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 0));
+-  EXPECT_FALSE(Demangle("_Z6foobarv", NULL, 0));  // Should not cause SEGV.
++  const size_t size = 10;
++  char tmp[size] = { 0 };
++  const char *demangled = "foobar()";
++  const char *mangled = "_Z6foobarv";
++  EXPECT_TRUE(Demangle(mangled, tmp, sizeof(tmp)));
++  // sizeof("foobar()") == size - 1
++  EXPECT_STREQ(demangled, tmp);
++  EXPECT_TRUE(Demangle(mangled, tmp, size - 1));
++  EXPECT_STREQ(demangled, tmp);
++  EXPECT_FALSE(Demangle(mangled, tmp, size - 2));  // Not enough.
++  EXPECT_FALSE(Demangle(mangled, tmp, 1));
++  EXPECT_FALSE(Demangle(mangled, tmp, 0));
++  EXPECT_FALSE(Demangle(mangled, NULL, 0));  // Should not cause SEGV.
+ }
+
+ // Test handling of functions suffixed with .clone.N, which is used by GCC
+@@ -123,6 +142,8 @@ TEST(Demangle, FromFile) {
+   }
+ }
+
++#endif
++
+ int main(int argc, char **argv) {
+ #ifdef HAVE_LIB_GFLAGS
+   ParseCommandLineFlags(&argc, &argv, true);
+diff --git c/src/logging.cc w/src/logging.cc
+index 0b5e6ee97..aa8a95eda 100644
+--- c/src/logging.cc
++++ w/src/logging.cc
+@@ -92,6 +92,15 @@ using std::fdopen;
+ #define fdopen _fdopen
+ #endif
+
++#if defined(OS_WINDOWS)
++_START_GOOGLE_NAMESPACE_
++namespace glog_internal_namespace_ {
++  void DumpTimeInfo();
++  void DumpStackInfo(int);
++}
++_END_GOOGLE_NAMESPACE_
++#endif
++
+ // There is no thread annotation support.
+ #define EXCLUSIVE_LOCKS_REQUIRED(mu)
+
+@@ -1466,8 +1475,17 @@ void LogMessage::RecordCrashReason(
+ static void logging_fail() ATTRIBUTE_NORETURN;
+
+ static void logging_fail() {
++#if defined(OS_WINDOWS)
++  // On Windows,the stack trace info needs to be dumped here instead
++  // of in the `SIGABRT` signal handler to avoid thread switching.
++  // The signal handler runs on the thread on which it was installed,
++  // making the stack trace irrelevant.
++  glog_internal_namespace_::DumpTimeInfo();
++  glog_internal_namespace_::DumpStackInfo(5);
++  FlushLogFilesUnsafe(0);
++#endif
+ #if defined(_DEBUG) && defined(_MSC_VER)
+-  // When debugging on windows, avoid the obnoxious dialog and make
++  // When debugging on Windows, avoid the obnoxious dialog and make
+   // it possible to continue past a LOG(FATAL) in the debugger
+   __debugbreak();
+ #else
+diff --git c/src/signalhandler.cc w/src/signalhandler.cc
+index a7aef8b99..a28b8b7c6 100644
+--- c/src/signalhandler.cc
++++ w/src/signalhandler.cc
+@@ -48,38 +48,11 @@
+
+ _START_GOOGLE_NAMESPACE_
+
+-// TOOD(hamaji): Use signal instead of sigaction?
+-#ifdef HAVE_SIGACTION
+-
+-namespace {
+-
+-// We'll install the failure signal handler for these signals.  We could
+-// use strsignal() to get signal names, but we don't use it to avoid
+-// introducing yet another #ifdef complication.
+-//
+-// The list should be synced with the comment in signalhandler.h.
+-const struct {
+-  int number;
+-  const char *name;
+-} kFailureSignals[] = {
+-  { SIGSEGV, "SIGSEGV" },
+-  { SIGILL, "SIGILL" },
+-  { SIGFPE, "SIGFPE" },
+-  { SIGABRT, "SIGABRT" },
+-  { SIGBUS, "SIGBUS" },
+-  { SIGTERM, "SIGTERM" },
+-};
++namespace glog_internal_namespace_ {
+
+-// Returns the program counter from signal context, NULL if unknown.
+-void* GetPC(void* ucontext_in_void) {
+-#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
+-  if (ucontext_in_void != NULL) {
+-    ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
+-    return (void*)context->PC_FROM_UCONTEXT;
+-  }
++#ifdef HAVE_SIGACTION
++  void DumpSignalInfo(int signal_number, siginfo_t *siginfo);
+ #endif
+-  return NULL;
+-}
+
+ // The class is used for formatting error messages.  We don't use printf()
+ // as it's not async signal safe.
+@@ -168,6 +141,76 @@ void DumpTimeInfo() {
+   g_failure_writer(buf, formatter.num_bytes_written());
+ }
+
++// Dumps information about the stack frame to STDERR.
++void DumpStackFrameInfo(const char* prefix, void* pc) {
++  // Get the symbol name.
++  const char *symbol = "(unknown)";
++  char symbolized[1024] = {};  // Big enough for a sane symbol.
++  // Symbolizes the previous address of pc because pc may be in the
++  // next function.
++  if (Symbolize(reinterpret_cast<char *>(pc) - 1,
++                symbolized, sizeof(symbolized))) {
++    symbol = symbolized;
++  }
++
++  char buf[1024];  // Big enough for stack frame info.
++  MinimalFormatter formatter(buf, sizeof(buf));
++
++  formatter.AppendString(prefix);
++  formatter.AppendString("@ ");
++  const int width = 2 * sizeof(void*) + 2;  // + 2  for "0x".
++  formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
++  formatter.AppendString(" ");
++  formatter.AppendString(symbol);
++  formatter.AppendString("\n");
++  g_failure_writer(buf, formatter.num_bytes_written());
++}
++
++// Argument is the number of frames to skip, excluding this function.
++void DumpStackInfo(int frames) {
++#ifdef HAVE_STACKTRACE
++  // Get the stack traces.
++  void *stack[32];
++  // +1 to exclude this function.
++  const int depth = GetStackTrace(stack, ARRAYSIZE(stack), frames + 1);
++  // Dump the stack traces.
++  for (int i = 0; i < depth; ++i) {
++    DumpStackFrameInfo("    ", stack[i]);
++  }
++#endif
++}
++
++// TOOD(hamaji): Use signal instead of sigaction?
++#ifdef HAVE_SIGACTION
++
++// We'll install the failure signal handler for these signals.  We could
++// use strsignal() to get signal names, but we don't use it to avoid
++// introducing yet another #ifdef complication.
++//
++// The list should be synced with the comment in signalhandler.h.
++const struct {
++  int number;
++  const char *name;
++} kFailureSignals[] = {
++  { SIGSEGV, "SIGSEGV" },
++  { SIGILL, "SIGILL" },
++  { SIGFPE, "SIGFPE" },
++  { SIGABRT, "SIGABRT" },
++  { SIGBUS, "SIGBUS" },
++  { SIGTERM, "SIGTERM" },
++};
++
++// Returns the program counter from signal context, NULL if unknown.
++void* GetPC(void* ucontext_in_void) {
++#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
++  if (ucontext_in_void != NULL) {
++    ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
++    return (void*)context->PC_FROM_UCONTEXT;
++  }
++#endif
++  return NULL;
++}
++
+ // Dumps information about the signal to STDERR.
+ void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
+   // Get the signal name.
+@@ -213,31 +256,6 @@ void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
+   g_failure_writer(buf, formatter.num_bytes_written());
+ }
+
+-// Dumps information about the stack frame to STDERR.
+-void DumpStackFrameInfo(const char* prefix, void* pc) {
+-  // Get the symbol name.
+-  const char *symbol = "(unknown)";
+-  char symbolized[1024];  // Big enough for a sane symbol.
+-  // Symbolizes the previous address of pc because pc may be in the
+-  // next function.
+-  if (Symbolize(reinterpret_cast<char *>(pc) - 1,
+-                symbolized, sizeof(symbolized))) {
+-    symbol = symbolized;
+-  }
+-
+-  char buf[1024];  // Big enough for stack frame info.
+-  MinimalFormatter formatter(buf, sizeof(buf));
+-
+-  formatter.AppendString(prefix);
+-  formatter.AppendString("@ ");
+-  const int width = 2 * sizeof(void*) + 2;  // + 2  for "0x".
+-  formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
+-  formatter.AppendString(" ");
+-  formatter.AppendString(symbol);
+-  formatter.AppendString("\n");
+-  g_failure_writer(buf, formatter.num_bytes_written());
+-}
+-
+ // Invoke the default signal handler.
+ void InvokeDefaultSignalHandler(int signal_number) {
+   struct sigaction sig_action;
+@@ -302,18 +320,14 @@ void FailureSignalHandler(int signal_number,
+   void *pc = GetPC(ucontext);
+   DumpStackFrameInfo("PC: ", pc);
+
+-#ifdef HAVE_STACKTRACE
+-  // Get the stack traces.
+-  void *stack[32];
+-  // +1 to exclude this function.
+-  const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
++  // Now dumb the signal info.
++#ifdef HAVE_SIGACTION
+   DumpSignalInfo(signal_number, signal_info);
+-  // Dump the stack traces.
+-  for (int i = 0; i < depth; ++i) {
+-    DumpStackFrameInfo("    ", stack[i]);
+-  }
+ #endif
+
++  // Now dump the stack trace.
++  DumpStackInfo(0);
++
+   // *** TRANSITION ***
+   //
+   // BEFORE this point, all code must be async-termination-safe!
+@@ -330,12 +344,15 @@ void FailureSignalHandler(int signal_number,
+   // Kill ourself by the default signal handler.
+   InvokeDefaultSignalHandler(signal_number);
+ }
+-
+-}  // namespace
+-
++#elif defined(OS_WINDOWS)
++void FailureSignalHandler(int signal) {
++  if (signal != SIGABRT) {
++    return;
++  }
++  exit(1);
++}
+ #endif  // HAVE_SIGACTION
+
+-namespace glog_internal_namespace_ {
+
+ bool IsFailureSignalHandlerInstalled() {
+ #ifdef HAVE_SIGACTION
+@@ -345,6 +362,9 @@ bool IsFailureSignalHandlerInstalled() {
+   sigaction(SIGABRT, NULL, &sig_action);
+   if (sig_action.sa_sigaction == &FailureSignalHandler)
+     return true;
++#elif defined(OS_WINDOWS)
++  // TODO: check if we installed it
++  return true;
+ #endif  // HAVE_SIGACTION
+   return false;
+ }
+@@ -363,11 +383,15 @@ void InstallFailureSignalHandler() {
+   for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
+     CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
+   }
++#elif defined(OS_WINDOWS)
++  typedef void (*SignalHandlerPointer)(int);
++  SignalHandlerPointer previousHandler;
++  previousHandler = signal(SIGABRT, &FailureSignalHandler);
+ #endif  // HAVE_SIGACTION
+ }
+
+ void InstallFailureWriter(void (*writer)(const char* data, int size)) {
+-#ifdef HAVE_SIGACTION
++#if defined(HAVE_SIGACTION) || defined(OS_WINDOWS)
+   g_failure_writer = writer;
+ #endif  // HAVE_SIGACTION
+ }
+diff --git c/src/stacktrace_unittest.cc w/src/stacktrace_unittest.cc
+index c1b3b36ff..ed95f8945 100644
+--- c/src/stacktrace_unittest.cc
++++ w/src/stacktrace_unittest.cc
+@@ -90,6 +90,32 @@ AddressRange expected_range[BACKTRACE_STEPS];
+       (prange)->end = ra;                                                \
+     }                                                                    \
+   } while (0)
++#elif defined(OS_WINDOWS)
++// Compiler Intrinsic _ReturnAddress documentation:
++// https://msdn.microsoft.com/en-us/library/64ez38eh(v=vs.140).aspx
++// This is equivalent to __builtin_return_address.
++#include <intrin.h>
++#pragma intrinsic(_ReturnAddress)
++#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange)           \
++  do {                                                                   \
++    (prange)->start = &fn;                                               \
++    (prange)->end = _ReturnAddress();                                    \
++    CHECK_LT((prange)->start, (prange)->end);                            \
++  } while (0)
++#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
++// MSVC may do the same thing as GCC (as noted above).
++// Adjust function range from _ReturnAddress.
++#define ADJUST_ADDRESS_RANGE_FROM_RA(prange)                             \
++  do {                                                                   \
++    void *ra = _ReturnAddress();                                         \
++    CHECK_LT((prange)->start, ra);                                       \
++    if (ra > (prange)->end) {                                            \
++      printf("Adjusting range from %p..%p to %p..%p\n",                  \
++             (prange)->start, (prange)->end,                             \
++             (prange)->start, ra);                                       \
++      (prange)->end = ra;                                                \
++    }                                                                    \
++  } while (0)
+ #else
+ // Assume the Check* functions below are not longer than 256 bytes.
+ #define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange)           \
+diff --git c/src/stacktrace_windows-inl.h w/src/stacktrace_windows-inl.h
+new file mode 100644
+index 000000000..dc23d109d
+--- /dev/null
++++ w/src/stacktrace_windows-inl.h
+@@ -0,0 +1,49 @@
++// Copyright (c) 2000 - 2007, Google Inc.
++// All rights reserved.
++//
++// Redistribution and use in source and binary forms, with or without
++// modification, are permitted provided that the following conditions are
++// met:
++//
++//     * Redistributions of source code must retain the above copyright
++// notice, this list of conditions and the following disclaimer.
++//     * Redistributions in binary form must reproduce the above
++// copyright notice, this list of conditions and the following disclaimer
++// in the documentation and/or other materials provided with the
++// distribution.
++//     * Neither the name of Google Inc. nor the names of its
++// contributors may be used to endorse or promote products derived from
++// this software without specific prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++//
++// Author: Andrew Schwartzmeyer
++//
++// Windows implementation - just use CaptureStackBackTrace
++
++#include "port.h"
++#include "stacktrace.h"
++#include "Dbghelp.h"
++
++_START_GOOGLE_NAMESPACE_
++
++int GetStackTrace(void** result, int max_depth, int skip_count) {
++  if (max_depth > 64) {
++    max_depth = 64;
++  }
++  skip_count++;  // we want to skip the current frame as well
++  // This API is thread-safe (moreover it walks only the current thread).
++  return CaptureStackBackTrace(skip_count, max_depth, result, NULL);
++}
++
++_END_GOOGLE_NAMESPACE_
+diff --git c/src/symbolize.cc w/src/symbolize.cc
+index f83c30973..0f10a86af 100644
+--- c/src/symbolize.cc
++++ w/src/symbolize.cc
+@@ -837,6 +837,57 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
+
+ _END_GOOGLE_NAMESPACE_
+
++#elif defined(OS_WINDOWS)
++
++#include "Dbghelp.h"
++
++_START_GOOGLE_NAMESPACE_
++
++class SymInitializer {
++public:
++  HANDLE process = NULL;
++  bool ready = false;
++  SymInitializer() {
++    // Initialize the symbol handler.
++    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx
++    process = GetCurrentProcess();
++    // Defer symbol loading.
++    // We do not request undecorated symbols with SYMOPT_UNDNAME
++    // because the mangling library calls UnDecorateSymbolName.
++    SymSetOptions(SYMOPT_DEFERRED_LOADS);
++    if (SymInitialize(process, NULL, true)) {
++      ready = true;
++    }
++  }
++  ~SymInitializer() {
++    SymCleanup(process);
++  }
++};
++
++__declspec(noinline) static bool SymbolizeAndDemangle(void *pc, char *out,
++                                                      int out_size) {
++  const SymInitializer symInitializer;
++  if (!symInitializer.ready) {
++    return false;
++  }
++  // Resolve symbol information from address.
++  // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx
++  char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
++  SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO*>(buf);
++  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
++  symbol->MaxNameLen = MAX_SYM_NAME;
++  bool ret = SymFromAddr(symInitializer.process, reinterpret_cast<DWORD64>(pc), 0, symbol);
++  if (ret && static_cast<int>(symbol->NameLen) < out_size) {
++      strncpy(out, symbol->Name, symbol->NameLen + 1);
++      // Symbolization succeeded.  Now we try to demangle the symbol.
++      DemangleInplace(out, out_size);
++      return true;
++  }
++  return false;
++}
++
++_END_GOOGLE_NAMESPACE_
++
+ #else
+ # error BUG: HAVE_SYMBOLIZE was wrongly set
+ #endif
+diff --git c/src/symbolize_unittest.cc w/src/symbolize_unittest.cc
+index 05cb8a11c..348a71b43 100644
+--- c/src/symbolize_unittest.cc
++++ w/src/symbolize_unittest.cc
+@@ -49,10 +49,22 @@ using namespace GFLAGS_NAMESPACE;
+ using namespace std;
+ using namespace GOOGLE_NAMESPACE;
+
+-#if defined(HAVE_STACKTRACE) && defined(__ELF__)
++#if defined(HAVE_STACKTRACE)
+
+ #define always_inline
+
++// A wrapper function for Symbolize() to make the unit test simple.
++static const char *TrySymbolize(void *pc) {
++  static char symbol[4096];
++  if (Symbolize(pc, symbol, sizeof(symbol))) {
++    return symbol;
++  } else {
++    return NULL;
++  }
++}
++
++# if defined(__ELF__)
++
+ // This unit tests make sense only with GCC.
+ // Uses lots of GCC specific features.
+ #if defined(__GNUC__) && !defined(__OPENCC__)
+@@ -70,16 +82,6 @@ using namespace GOOGLE_NAMESPACE;
+ #  endif  // defined(__i386__) || defined(__x86_64__)
+ #endif
+
+-// A wrapper function for Symbolize() to make the unit test simple.
+-static const char *TrySymbolize(void *pc) {
+-  static char symbol[4096];
+-  if (Symbolize(pc, symbol, sizeof(symbol))) {
+-    return symbol;
+-  } else {
+-    return NULL;
+-  }
+-}
+-
+ // Make them C linkage to avoid mangled names.
+ extern "C" {
+ void nonstatic_func() {
+@@ -340,11 +342,42 @@ void ATTRIBUTE_NOINLINE TestWithReturnAddress() {
+ #endif
+ }
+
++# elif defined(OS_WINDOWS)
++
++#include <intrin.h>
++#pragma intrinsic(_ReturnAddress)
++
++struct Foo {
++  static void func(int x);
++};
++
++__declspec(noinline) void Foo::func(int x) {
++  volatile int a = x;
++  ++a;
++}
++
++TEST(Symbolize, SymbolizeWithDemangling) {
++  Foo::func(100);
++  const char* ret = TrySymbolize((void *)(&Foo::func));
++  EXPECT_STREQ("public: static void __cdecl Foo::func(int)", ret);
++}
++
++__declspec(noinline) void TestWithReturnAddress() {
++  void *return_address = _ReturnAddress();
++  const char *symbol = TrySymbolize(return_address);
++  CHECK(symbol != NULL);
++  CHECK_STREQ(symbol, "main");
++  cout << "Test case TestWithReturnAddress passed." << endl;
++}
++# endif  // __ELF__
++#endif  // HAVE_STACKTRACE
++
+ int main(int argc, char **argv) {
+   FLAGS_logtostderr = true;
+   InitGoogleLogging(argv[0]);
+   InitGoogleTest(&argc, argv);
+-#ifdef HAVE_SYMBOLIZE
++#if defined(HAVE_SYMBOLIZE)
++# if defined(__ELF__)
+   // We don't want to get affected by the callback interface, that may be
+   // used to install some callback function at InitGoogle() time.
+   InstallSymbolizeCallback(NULL);
+@@ -353,18 +386,15 @@ int main(int argc, char **argv) {
+   TestWithPCInsideNonInlineFunction();
+   TestWithReturnAddress();
+   return RUN_ALL_TESTS();
+-#else
+-  return 0;
+-#endif
+-}
+-
+-#else
+-int main() {
+-#ifdef HAVE_SYMBOLIZE
++# elif defined(OS_WINDOWS)
++  TestWithReturnAddress();
++  return RUN_ALL_TESTS();
++# else
+   printf("PASS (no symbolize_unittest support)\n");
++  return 0;
++# endif  // __ELF__
+ #else
+   printf("PASS (no symbolize support)\n");
+-#endif
+   return 0;
++#endif
+ }
+-#endif  // HAVE_STACKTRACE
+diff --git c/src/utilities.h w/src/utilities.h
+index 5f79968ef..10f98b24a 100644
+--- c/src/utilities.h
++++ w/src/utilities.h
+@@ -97,6 +97,8 @@
+ //    malloc() from the unwinder.  This is a problem because we're
+ //    trying to use the unwinder to instrument malloc().
+ //
++// 4) The Windows API CaptureStackTrace.
++//
+ // Note: if you add a new implementation here, make sure it works
+ // correctly when GetStackTrace() is called with max_depth == 0.
+ // Some code may do that.
+@@ -110,6 +112,8 @@
+ #  define STACKTRACE_H "stacktrace_x86_64-inl.h"
+ # elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
+ #  define STACKTRACE_H "stacktrace_powerpc-inl.h"
++# elif defined(OS_WINDOWS)
++#  define STACKTRACE_H "stacktrace_windows-inl.h"
+ # endif
+ #endif
+
+@@ -127,6 +131,9 @@
+ #elif defined(OS_MACOSX) && defined(HAVE_DLADDR)
+ // Use dladdr to symbolize.
+ # define HAVE_SYMBOLIZE
++#elif defined(OS_WINDOWS)
++// Use Dbghelp.dll to symbolize
++# define HAVE_SYMBOLIZE
+ #endif
+
+ #ifndef ARRAYSIZE


[2/2] mesos git commit: Windows: Updated libprocess CMake setup for Glog patch.

Posted by jo...@apache.org.
Windows: Updated libprocess CMake setup for Glog patch.

The additional Windows library `Dbghelp` must be linked for the
in addition to glog, in order to enable stack traces.

NOTE: CMake's dependency graph does not pull in the `Dbghelp` library
automatically as the glog dependency is added into Mesos as an
"external" project.  If we were to, instead, add glog's CMake files
to the build system directly (such as, as a git submodule), glog's
targets would be inherited.

Review: https://reviews.apache.org/r/57491/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/5d3908a4
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/5d3908a4
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/5d3908a4

Branch: refs/heads/master
Commit: 5d3908a4c3312a41ad801683089ea14eae9b0360
Parents: ef3ebf3
Author: Andrew Schwartzmeyer <an...@schwartzmeyer.com>
Authored: Mon Mar 13 18:16:23 2017 -0700
Committer: Joseph Wu <jo...@apache.org>
Committed: Tue Mar 14 10:38:08 2017 -0700

----------------------------------------------------------------------
 .../libprocess/cmake/Process3rdpartyConfigure.cmake   | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5d3908a4/3rdparty/libprocess/cmake/Process3rdpartyConfigure.cmake
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/cmake/Process3rdpartyConfigure.cmake b/3rdparty/libprocess/cmake/Process3rdpartyConfigure.cmake
index e9eabd0..83406f2 100644
--- a/3rdparty/libprocess/cmake/Process3rdpartyConfigure.cmake
+++ b/3rdparty/libprocess/cmake/Process3rdpartyConfigure.cmake
@@ -31,9 +31,9 @@ EXTERNAL("protobuf"    ${PROTOBUF_VERSION}    "${MESOS_3RDPARTY_BIN}")
 if (NOT WIN32)
   EXTERNAL("glog" ${GLOG_VERSION} "${MESOS_3RDPARTY_BIN}")
 elseif (WIN32)
-  # Glog 0.3.3 does not compile out of the box on Windows. Therefore, we
-  # require 0.3.4.
-  EXTERNAL("glog" "0.3.4" "${MESOS_3RDPARTY_BIN}")
+  # Glog 0.3.3 does not compile out of the box on Windows.
+  # Therefore, we require a specific commit on glog master.
+  EXTERNAL("glog" "da816ea70" "${MESOS_3RDPARTY_BIN}")
 
   # NOTE: We expect cURL and zlib exist on Unix (usually pulled in with a
   # package manager), but Windows has no package manager, so we have to go
@@ -111,6 +111,14 @@ if (WIN32)
 
   # Windows requires a static build of zlib.
   set(ZLIB_LFLAG     zlibstaticd)
+
+  # Windows requires Dbghelp.lib when linking to glog.
+  # NOTE: CMake's dependency graph does not pull in the `Dbghelp` library
+  # automatically as the glog dependency is added into Mesos as an
+  # "external" project.  If we were to, instead, add glog's CMake files
+  # to the build system directly (such as, as a git submodule), glog's
+  # targets would be inherited.
+  set(GLOG_LFLAG     glog Dbghelp)
 else (WIN32)
   set(CURL_LFLAG     curl)
   set(DL_LFLAG       dl)