Bug 1202386: Add logging macros for HAL IPC, r=shuang
authorThomas Zimmermann <tdz@users.sourceforge.net>
Thu, 10 Sep 2015 11:32:26 +0200
changeset 294240 c0e2d913c6017354c2c4ef2f6a56d5aac619511e
parent 294239 d59ea14e38a77451863f5854fc96e97519adbf37
child 294241 f353659e96a7acaf3b23be1469ca90206107e60a
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshuang
bugs1202386
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1202386: Add logging macros for HAL IPC, r=shuang The code for packing and unpacking IPC messages does currently not output detailed error message. This patch adds macros that display information about the failed operation and arguments. The overhead of the macros is small and the fast path can be inlined.
ipc/hal/DaemonSocketPDUHelpers.cpp
ipc/hal/DaemonSocketPDUHelpers.h
--- a/ipc/hal/DaemonSocketPDUHelpers.cpp
+++ b/ipc/hal/DaemonSocketPDUHelpers.cpp
@@ -2,34 +2,71 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DaemonSocketPDUHelpers.h"
 #include <limits>
 
+// Enable this constant to abort Gecko on IPC errors. This is helpful
+// for debugging, but should *never* be enabled by default.
+#define MOZ_HAL_ABORT_ON_IPC_ERRORS (0)
+
 #ifdef CHROMIUM_LOG
 #undef CHROMIUM_LOG
 #endif
 
 #if defined(MOZ_WIDGET_GONK)
+
 #include <android/log.h>
-#define CHROMIUM_LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "I/O", args);
+
+#define CHROMIUM_LOG(args...) \
+  __android_log_print(ANDROID_LOG_INFO, "HAL-IPC", args);
+
+#define CHROMIUM_LOG_VA(fmt, ap) \
+  __android_log_vprint(ANDROID_LOG_INFO, "HAL-IPC", fmt, ap);
+
 #else
+
 #include <stdio.h>
+
 #define IODEBUG true
-#define CHROMIUM_LOG(args...) if (IODEBUG) printf(args);
+#define CHROMIUM_LOG(args...) if (IODEBUG) { printf(args); }
+#define CHROMIUM_LOG_VA(fmt, ap) if (IODEBUG) { vprintf(fmt, ap); }
+
 #endif
 
 namespace mozilla {
 namespace ipc {
 namespace DaemonSocketPDUHelpers {
 
 //
+// Logging
+//
+
+namespace detail {
+
+void
+LogProtocolError(const char* aFmt, ...)
+{
+  va_list ap;
+
+  va_start(ap, aFmt);
+  CHROMIUM_LOG_VA(aFmt, ap);
+  va_end(ap);
+
+  if (MOZ_HAL_ABORT_ON_IPC_ERRORS) {
+    MOZ_CRASH("HAL IPC protocol error");
+  }
+}
+
+} // namespace detail
+
+//
 // Conversion
 //
 
 nsresult
 Convert(bool aIn, uint8_t& aOut)
 {
   static const uint8_t sValue[] = {
     [false] = 0x00,
--- a/ipc/hal/DaemonSocketPDUHelpers.h
+++ b/ipc/hal/DaemonSocketPDUHelpers.h
@@ -30,16 +30,88 @@ struct DaemonSocketPDUHeader {
   uint8_t mService;
   uint8_t mOpcode;
   uint16_t mLength;
 };
 
 namespace DaemonSocketPDUHelpers {
 
 //
+// Logging
+//
+// The HAL IPC logging macros below print clear error messages for
+// failed IPC operations. Use |MOZ_HAL_IPC_CONVERT_WARN_IF|,
+// |MOZ_HAL_IPC_PACK_WARN_IF| and |MOZ_HAL_IPC_UNPACK_WARN_IF| to
+// test for failures when processing PDUs.
+//
+// All macros accept the test condition as their first argument, and
+// additional type information: the convert macro takes the input and
+// output types, the pack macro takes the input type, and the unpack
+// macro takes output type. All macros return the result of the test
+// condition. If the test fails (i.e., the condition is true), they
+// output a warning to the log.
+//
+// Don't call the functions in the detail namespace. They are helpers
+// and not for general use.
+//
+
+namespace detail {
+
+void
+LogProtocolError(const char*, ...);
+
+inline bool
+ConvertWarnIfImpl(const char* aFile, unsigned long aLine,
+                  bool aCondition, const char* aExpr, const char* aIn,
+                  const char* aOut)
+{
+  if (MOZ_UNLIKELY(aCondition)) {
+    LogProtocolError("%s:%d: Convert('%s' to '%s') failed: %s",
+                     aFile, aLine, aIn, aOut, aExpr);
+  }
+  return aCondition;
+}
+
+inline bool
+PackWarnIfImpl(const char* aFile, unsigned long aLine,
+               bool aCondition, const char* aExpr, const char* aIn)
+{
+  if (MOZ_UNLIKELY(aCondition)) {
+    LogProtocolError("%s:%d: Pack('%s') failed: %s",
+                     aFile, aLine, aIn, aExpr);
+  }
+  return aCondition;
+}
+
+inline bool
+UnpackWarnIfImpl(const char* aFile, unsigned long aLine,
+                 bool aCondition, const char* aExpr, const char* aOut)
+{
+  if (MOZ_UNLIKELY(aCondition)) {
+    LogProtocolError("%s:%d: Unpack('%s') failed: %s",
+                     aFile, aLine, aOut, aExpr);
+  }
+  return aCondition;
+}
+
+} // namespace detail
+
+#define MOZ_HAL_IPC_CONVERT_WARN_IF(condition, in, out) \
+  ::mozilla::ipc::DaemonSocketPDUHelpers::detail:: \
+    ConvertWarnIfImpl(__FILE__, __LINE__, condition, #condition, #in, #out)
+
+#define MOZ_HAL_IPC_PACK_WARN_IF(condition, in) \
+  ::mozilla::ipc::DaemonSocketPDUHelpers::detail:: \
+    PackWarnIfImpl(__FILE__, __LINE__, condition, #condition, #in)
+
+#define MOZ_HAL_IPC_UNPACK_WARN_IF(condition, out) \
+  ::mozilla::ipc::DaemonSocketPDUHelpers::detail:: \
+    UnpackWarnIfImpl(__FILE__, __LINE__, condition, #condition, #out)
+
+//
 // Conversion
 //
 // PDUs can only store primitive data types, such as integers or
 // byte arrays. Gecko often uses more complex data types, such as
 // enumators or stuctures. Conversion functions convert between
 // primitive data and internal Gecko's data types during a PDU's
 // packing and unpacking.
 //