Merge "Fixed failing 2015 bot3 test."
diff --git a/aos/build/aos.gyp b/aos/build/aos.gyp
index 2c44ed6..bbdb2c9 100644
--- a/aos/build/aos.gyp
+++ b/aos/build/aos.gyp
@@ -16,6 +16,7 @@
         ['OS=="linux"', {
           'sources': [
             '<(AOS)/linux_code/logging/linux_interface.cc',
+            '<(AOS)/common/logging/context.cc',
           ],
           'dependencies': [
             '<(AOS)/linux_code/linux_code.gyp:complex_thread_local',
diff --git a/aos/build/aos_all.gyp b/aos/build/aos_all.gyp
index 195997a..b546087 100644
--- a/aos/build/aos_all.gyp
+++ b/aos/build/aos_all.gyp
@@ -37,6 +37,7 @@
         '<(AOS)/common/common.gyp:once_test',
         '<(AOS)/common/common.gyp:event_test',
         '<(AOS)/common/common.gyp:queue_testutils_test',
+        '<(AOS)/common/common.gyp:transaction_test',
         '<(AOS)/common/logging/logging.gyp:logging_impl_test',
         '<(AOS)/common/util/util.gyp:options_test',
         '<(AOS)/common/common.gyp:queue_test',
diff --git a/aos/common/BUILD b/aos/common/BUILD
index 1691e22..4262b60 100644
--- a/aos/common/BUILD
+++ b/aos/common/BUILD
@@ -89,12 +89,23 @@
 )
 
 cc_library(
-  name = 'event',
+  name = 'real_event',
+  visibility = ['//aos/linux_code/ipc_lib:__pkg__'],
   hdrs = [
     'event.h',
   ],
   deps = [
     '//aos/linux_code/ipc_lib:aos_sync',
+    ':time',
+  ],
+)
+
+cc_library(
+  # Use this one!
+  # TODO(Brian): Remove this mess...
+  name = 'event',
+  deps = [
+    '//aos/linux_code/ipc_lib:event',
   ],
 )
 
@@ -301,19 +312,29 @@
   ],
   deps = [
     '//aos/testing:googletest',
-    '//aos/linux_code/ipc_lib:event',
+    ':event',
     ':queue_testutils',
     ':time',
   ],
 )
 
 cc_library(
-  name = 'condition',
+  name = 'real_condition',
+  visibility = ['//aos/linux_code/ipc_lib:__pkg__'],
   hdrs = [
     'condition.h',
   ],
 )
 
+cc_library(
+  # Use this one!
+  # TODO(Brian): Remove this mess...
+  name = 'condition',
+  deps = [
+    '//aos/linux_code/ipc_lib:condition',
+  ],
+)
+
 cc_test(
   name = 'condition_test',
   srcs = [
@@ -321,7 +342,7 @@
   ],
   deps = [
     '//aos/testing:googletest',
-    '//aos/linux_code/ipc_lib:condition',
+    ':condition',
     '//aos/common/util:thread',
     ':time',
     '//aos/linux_code/ipc_lib:mutex',
@@ -379,3 +400,27 @@
     ':die',
   ],
 )
+
+cc_library(
+  name = 'transaction',
+  hdrs = [
+    'transaction.h',
+  ],
+  deps = [
+    '//aos/common/logging:logging_interface',
+    '//aos/common/util:compiler_memory_barrier',
+  ],
+)
+
+cc_test(
+  name = 'transaction_test',
+  srcs = [
+    'transaction_test.cc',
+  ],
+  deps = [
+    ':transaction',
+    '//aos/testing:googletest',
+    '//aos/common/logging',
+    '//aos/common/util:death_test_log_implementation',
+  ],
+)
diff --git a/aos/common/actions/BUILD b/aos/common/actions/BUILD
index 6669ef1..de13464 100644
--- a/aos/common/actions/BUILD
+++ b/aos/common/actions/BUILD
@@ -54,6 +54,6 @@
     '//aos/common:queues',
     '//aos/common:time',
     ':action_queue',
-    '//aos/linux_code/ipc_lib:event',
+    '//aos/common:event',
   ],
 )
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index c9e1b6a..14619ad 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -253,10 +253,12 @@
       ],
       'dependencies': [
         '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        'time',
         '<(AOS)/build/aos.gyp:logging_interface',
       ],
       'export_dependent_settings': [
         '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        'time',
       ],
     },
     {
@@ -361,5 +363,31 @@
         'die',
       ],
     },
+    {
+      'target_name': 'transaction',
+      'type': 'static_library',
+      'sources': [
+        #'transaction.h',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+    },
+    {
+      'target_name': 'transaction_test',
+      'type': 'executable',
+      'sources': [
+        'transaction_test.cc',
+      ],
+      'dependencies': [
+        'transaction',
+        '<(EXTERNALS):gtest',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:death_test_log_implementation',
+      ],
+    },
   ],
 }
diff --git a/aos/common/event.h b/aos/common/event.h
index 9839d41..b3ee87b 100644
--- a/aos/common/event.h
+++ b/aos/common/event.h
@@ -1,6 +1,8 @@
 #ifndef AOS_COMMON_EVENT_H_
 #define AOS_COMMON_EVENT_H_
 
+#include "aos/common/time.h"
+
 #include "aos/linux_code/ipc_lib/aos_sync.h"
 
 namespace aos {
@@ -37,6 +39,11 @@
   // Waits for the event to be set. Returns immediately if it is already set.
   void Wait();
 
+  // Waits for the event to be set or until timeout has elapsed. Returns
+  // immediately if it is already set.
+  // Returns true if the event was Set or false if the timeout expired.
+  bool WaitTimeout(const ::aos::time::Time &timeout);
+
   // Wakes up all Wait()ers and sets the event (atomically).
   void Set();
   // Unsets the event so future Wait() callers will block instead of returning
diff --git a/aos/common/event_test.cc b/aos/common/event_test.cc
index d8671eb..7331309 100644
--- a/aos/common/event_test.cc
+++ b/aos/common/event_test.cc
@@ -12,7 +12,7 @@
 
 class EventTest : public ::testing::Test {
  public:
-  Event test_event;
+  Event test_event_;
 
  protected:
   void SetUp() override {
@@ -22,13 +22,13 @@
 
 // Makes sure that basic operations with no blocking or anything work.
 TEST_F(EventTest, Basic) {
-  EXPECT_FALSE(test_event.Clear());
-  EXPECT_FALSE(test_event.Clear());
+  EXPECT_FALSE(test_event_.Clear());
+  EXPECT_FALSE(test_event_.Clear());
 
-  test_event.Set();
-  test_event.Wait();
-  EXPECT_TRUE(test_event.Clear());
-  EXPECT_FALSE(test_event.Clear());
+  test_event_.Set();
+  test_event_.Wait();
+  EXPECT_TRUE(test_event_.Clear());
+  EXPECT_FALSE(test_event_.Clear());
 }
 
 // Tests that tsan understands that events establish a happens-before
@@ -36,13 +36,13 @@
 TEST_F(EventTest, ThreadSanitizer) {
   for (int i = 0; i < 3000; ++i) {
     int variable = 0;
-    test_event.Clear();
+    test_event_.Clear();
     ::std::thread thread([this, &variable]() {
-      test_event.Wait();
+      test_event_.Wait();
       --variable;
     });
     ++variable;
-    test_event.Set();
+    test_event_.Set();
     thread.join();
     EXPECT_EQ(0, variable);
   }
@@ -56,13 +56,33 @@
   ::std::thread thread([this, &start_time, &finish_time, &started]() {
     start_time = time::Time::Now();
     started.Set();
-    test_event.Wait();
+    test_event_.Wait();
     finish_time = time::Time::Now();
   });
   static const time::Time kWaitTime = time::Time::InSeconds(0.05);
   started.Wait();
   time::SleepFor(kWaitTime);
-  test_event.Set();
+  test_event_.Set();
+  thread.join();
+  EXPECT_GE(finish_time - start_time, kWaitTime);
+}
+
+TEST_F(EventTest, WaitTimeout) {
+  EXPECT_FALSE(test_event_.WaitTimeout(time::Time::InSeconds(0.05)));
+
+  time::Time start_time, finish_time;
+  // Without this, it sometimes manages to fail under tsan.
+  Event started;
+  ::std::thread thread([this, &start_time, &finish_time, &started]() {
+    start_time = time::Time::Now();
+    started.Set();
+    EXPECT_TRUE(test_event_.WaitTimeout(time::Time::InSeconds(0.5)));
+    finish_time = time::Time::Now();
+  });
+  static const time::Time kWaitTime = time::Time::InSeconds(0.05);
+  started.Wait();
+  time::SleepFor(kWaitTime);
+  test_event_.Set();
   thread.join();
   EXPECT_GE(finish_time - start_time, kWaitTime);
 }
diff --git a/aos/common/logging/BUILD b/aos/common/logging/BUILD
index 9223c44..78d1cbd 100644
--- a/aos/common/logging/BUILD
+++ b/aos/common/logging/BUILD
@@ -71,14 +71,11 @@
   srcs = [
     'logging_interface.cc',
   ],
-  copts = [
-    # TODO(austin): This is wrong.
-    '-Wno-error=format-nonliteral'
-  ],
   deps = [
     '//aos/common:die',
     '//aos/common/libc:aos_strerror',
     '//aos/linux_code/logging:linux_interface',
+    '//aos/common:macros',
   ],
 )
 
diff --git a/aos/common/logging/logging_impl.h b/aos/common/logging/logging_impl.h
index ab4b728..5fdeec7 100644
--- a/aos/common/logging/logging_impl.h
+++ b/aos/common/logging/logging_impl.h
@@ -106,18 +106,6 @@
   return LOG_UNKNOWN;
 }
 
-// Takes a message and logs it. It will set everything up and then call DoLog
-// for the current LogImplementation.
-void VLog(log_level level, const char *format, va_list ap)
-    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
-// Adds to the saved up message.
-void VCork(int line, const char *function, const char *format, va_list ap)
-    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
-// Actually logs the saved up message.
-void VUnCork(int line, const char *function, log_level level, const char *file,
-             const char *format, va_list ap)
-    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 5, 0)));
-
 // Will call VLog with the given arguments for the next logger in the chain.
 void LogNext(log_level level, const char *format, ...)
   __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 3)));
@@ -217,18 +205,6 @@
 // Prints message to output.
 void PrintMessage(FILE *output, const LogMessage &message);
 
-// Prints format (with ap) into output and correctly deals with the result
-// being too long etc.
-size_t ExecuteFormat(char *output, size_t output_size, const char *format,
-                     va_list ap)
-    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
-
-// Runs the given function with the current LogImplementation (handles switching
-// it out while running function etc).
-// levels is how many LogImplementations to not use off the stack.
-void RunWithCurrentImplementation(
-    int levels, ::std::function<void(LogImplementation *)> function);
-
 }  // namespace internal
 }  // namespace logging
 }  // namespace aos
diff --git a/aos/common/logging/logging_interface.h b/aos/common/logging/logging_interface.h
index af591ee..97587bf 100644
--- a/aos/common/logging/logging_interface.h
+++ b/aos/common/logging/logging_interface.h
@@ -7,6 +7,7 @@
 #include <functional>
 
 #include "aos/common/logging/logging.h"
+#include "aos/common/macros.h"
 
 namespace aos {
 
@@ -17,6 +18,18 @@
 namespace aos {
 namespace logging {
 
+// Takes a message and logs it. It will set everything up and then call DoLog
+// for the current LogImplementation.
+void VLog(log_level level, const char *format, va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
+// Adds to the saved up message.
+void VCork(int line, const char *function, const char *format, va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
+// Actually logs the saved up message.
+void VUnCork(int line, const char *function, log_level level, const char *file,
+             const char *format, va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 5, 0)));
+
 // Represents a system that can actually take log messages and do something
 // useful with them.
 // All of the code (transitively too!) in the DoLog here can make
@@ -90,6 +103,21 @@
   LogImplementation *next_;
 };
 
+namespace internal {
+
+// Prints format (with ap) into output and correctly deals with the result
+// being too long etc.
+size_t ExecuteFormat(char *output, size_t output_size, const char *format,
+                     va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
+
+// Runs the given function with the current LogImplementation (handles switching
+// it out while running function etc).
+// levels is how many LogImplementations to not use off the stack.
+void RunWithCurrentImplementation(
+    int levels, ::std::function<void(LogImplementation *)> function);
+
+}  // namespace internal
 }  // namespace logging
 }  // namespace aos
 
diff --git a/aos/common/time.cc b/aos/common/time.cc
index 7318afb..d1985b5 100644
--- a/aos/common/time.cc
+++ b/aos/common/time.cc
@@ -38,7 +38,8 @@
          static_cast<uintmax_t>(clock), &temp);
   }
 
-  const timespec offset = (global_core == nullptr)
+  const timespec offset = (&global_core == nullptr || global_core == nullptr ||
+                           global_core->mem_struct == nullptr)
                               ? timespec{0, 0}
                               : global_core->mem_struct->time_offset;
   return Time(temp) + Time(offset);
@@ -223,7 +224,9 @@
 }
 
 void OffsetToNow(const Time &now) {
+  CHECK_NOTNULL(&global_core);
   CHECK_NOTNULL(global_core);
+  CHECK_NOTNULL(global_core->mem_struct);
   global_core->mem_struct->time_offset.tv_nsec = 0;
   global_core->mem_struct->time_offset.tv_sec = 0;
   global_core->mem_struct->time_offset = (now - Time::Now()).ToTimespec();
diff --git a/aos/common/transaction.h b/aos/common/transaction.h
new file mode 100644
index 0000000..e6e9e41
--- /dev/null
+++ b/aos/common/transaction.h
@@ -0,0 +1,103 @@
+#ifndef AOS_COMMON_TRANSACTION_H_
+#define AOS_COMMON_TRANSACTION_H_
+
+#include <stdint.h>
+
+#include <array>
+
+#include "aos/common/util/compiler_memory_barrier.h"
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace transaction {
+
+// Manages a LIFO stack of Work objects. Designed to help implement transactions
+// by providing a safe way to undo things etc.
+//
+// number_works Work objects are created statically and then Create is called on
+// each as it is added to the stack. When the work should do whatever it does,
+// DoWork() will be called. The work objects get no notification when they are
+// dropped off of the stack.
+//
+// Work::DoWork() must be idempotent because it may get called multiple times if
+// CompleteWork() is interrupted part of the way through.
+//
+// This class handles compiler memory barriers etc to make sure only fully
+// created works are ever invoked, and each work will be fully created by the
+// time AddWork returns. This does not mean it's safe for multiple threads to
+// interact with an instance of this class at the same time.
+template <class Work, int number_works>
+class WorkStack {
+ public:
+  // Calls DoWork() on all the works that have been added and then removes them
+  // all from the stack.
+  void CompleteWork() {
+    int current = stack_index_;
+    while (current > 0) {
+      stack_.at(--current).DoWork();
+    }
+    aos_compiler_memory_barrier();
+    stack_index_ = 0;
+    aos_compiler_memory_barrier();
+  }
+
+  // Drops all works that have been added.
+  void DropWork() {
+    stack_index_ = 0;
+    aos_compiler_memory_barrier();
+  }
+
+  // Returns true if we have any works to complete right now.
+  bool HasWork() const { return stack_index_ != 0; }
+
+  // Forwards all of its arguments to Work::Create, which it calls on the next
+  // work to be added.
+  template <class... A>
+  void AddWork(A &&... a) {
+    if (stack_index_ >= number_works) {
+      LOG(FATAL, "too many works\n");
+    }
+    stack_.at(stack_index_).Create(::std::forward<A>(a)...);
+    aos_compiler_memory_barrier();
+    ++stack_index_;
+    aos_compiler_memory_barrier();
+  }
+
+ private:
+  // The next index into stack_ for a new work to be added.
+  int stack_index_ = 0;
+  ::std::array<Work, number_works> stack_;
+};
+
+// When invoked, sets *pointer to the value it had when this work was Created.
+template <class T>
+class RestoreValueWork {
+ public:
+  void Create(T *pointer) {
+    pointer_ = pointer;
+    value_ = *pointer;
+  }
+  void DoWork() {
+    *pointer_ = value_;
+  }
+
+ private:
+  T *pointer_;
+  T value_;
+};
+
+// Handles the casting necessary to restore any kind of pointer.
+class RestorePointerWork : public RestoreValueWork<void *> {
+ public:
+  template <class T>
+  void Create(T **pointer) {
+    static_assert(sizeof(T *) == sizeof(void *),
+                  "that's a weird pointer");
+    RestoreValueWork<void *>::Create(reinterpret_cast<void **>(pointer));
+  }
+};
+
+}  // namespace transaction
+}  // namespace aos
+
+#endif  // AOS_COMMON_TRANSACTION_H_
diff --git a/aos/common/transaction_test.cc b/aos/common/transaction_test.cc
new file mode 100644
index 0000000..e74fd69
--- /dev/null
+++ b/aos/common/transaction_test.cc
@@ -0,0 +1,106 @@
+#include "aos/common/transaction.h"
+
+#include <vector>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/util/death_test_log_implementation.h"
+
+namespace aos {
+namespace transaction {
+namespace testing {
+
+class WorkStackTest : public ::testing::Test {
+ public:
+  // Contains an index which it adds to the created_works and invoked_works
+  // vectors of its containing WorkStackTest.
+  class TestWork {
+   public:
+    void Create(WorkStackTest *test, int i) {
+      test->created_works()->push_back(i);
+      i_ = i;
+      test_ = test;
+    }
+    void DoWork() {
+      test_->invoked_works()->push_back(i_);
+    }
+
+    int i() const { return i_; }
+
+   private:
+    int i_;
+    WorkStackTest *test_;
+  };
+
+  ::std::vector<int> *created_works() { return &created_works_; }
+  ::std::vector<int> *invoked_works() { return &invoked_works_; }
+  WorkStack<TestWork, 20> *work_stack() { return &work_stack_; }
+
+  // Creates a TestWork with index i and adds it to work_stack().
+  void CreateWork(int i) {
+    work_stack_.AddWork(this, i);
+  }
+
+ private:
+  ::std::vector<int> created_works_, invoked_works_;
+  WorkStack<TestWork, 20> work_stack_;
+};
+
+typedef WorkStackTest WorkStackDeathTest;
+
+TEST_F(WorkStackTest, Basic) {
+  EXPECT_FALSE(work_stack()->HasWork());
+  EXPECT_EQ(0u, created_works()->size());
+  EXPECT_EQ(0u, invoked_works()->size());
+
+  CreateWork(971);
+  EXPECT_TRUE(work_stack()->HasWork());
+  EXPECT_EQ(1u, created_works()->size());
+  EXPECT_EQ(0u, invoked_works()->size());
+  EXPECT_EQ(971, created_works()->at(0));
+
+  work_stack()->CompleteWork();
+  EXPECT_FALSE(work_stack()->HasWork());
+  EXPECT_EQ(1u, created_works()->size());
+  EXPECT_EQ(1u, invoked_works()->size());
+  EXPECT_EQ(971, invoked_works()->at(0));
+}
+
+TEST_F(WorkStackTest, DropWork) {
+  CreateWork(971);
+  CreateWork(254);
+  EXPECT_EQ(2u, created_works()->size());
+
+  work_stack()->DropWork();
+  EXPECT_FALSE(work_stack()->HasWork());
+  work_stack()->CompleteWork();
+  EXPECT_EQ(0u, invoked_works()->size());
+}
+
+// Tests that the works get run in the correct order.
+TEST_F(WorkStackTest, InvocationOrder) {
+  CreateWork(971);
+  CreateWork(254);
+  CreateWork(1678);
+
+  work_stack()->CompleteWork();
+  EXPECT_EQ((::std::vector<int>{971, 254, 1678}), *created_works());
+  EXPECT_EQ((::std::vector<int>{1678, 254, 971}), *invoked_works());
+}
+
+// Tests that it handles adding too many works intelligently.
+TEST_F(WorkStackDeathTest, TooManyWorks) {
+  logging::Init();
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        for (int i = 0; i < 1000; ++i) {
+          CreateWork(i);
+        }
+      },
+      ".*too many works.*");
+}
+
+}  // namespace testing
+}  // namespace transaction
+}  // namespace aos
diff --git a/aos/common/util/BUILD b/aos/common/util/BUILD
index 646f3bf..bd70463 100644
--- a/aos/common/util/BUILD
+++ b/aos/common/util/BUILD
@@ -172,3 +172,10 @@
     '//aos/testing:googletest',
   ],
 )
+
+cc_library(
+  name = 'compiler_memory_barrier',
+  hdrs = [
+    'compiler_memory_barrier.h',
+  ],
+)
diff --git a/aos/common/util/compiler_memory_barrier.h b/aos/common/util/compiler_memory_barrier.h
new file mode 100644
index 0000000..5126941
--- /dev/null
+++ b/aos/common/util/compiler_memory_barrier.h
@@ -0,0 +1,11 @@
+#ifndef AOS_COMMON_UTIL_COMPILER_MEMORY_BARRIER_H_
+#define AOS_COMMON_UTIL_COMPILER_MEMORY_BARRIER_H_
+
+// Prevents the compiler from reordering memory operations around this.
+// Using this function makes it clearer what you're doing and easier to be
+// portable.
+static inline void aos_compiler_memory_barrier(void) {
+  __asm__ __volatile__("" ::: "memory");
+}
+
+#endif  // AOS_COMMON_UTIL_COMPILER_MEMORY_BARRIER_H_
diff --git a/aos/linux_code/ipc_lib/BUILD b/aos/linux_code/ipc_lib/BUILD
index 47b9e8e..576774e 100644
--- a/aos/linux_code/ipc_lib/BUILD
+++ b/aos/linux_code/ipc_lib/BUILD
@@ -125,12 +125,13 @@
 
 cc_library(
   name = 'condition',
+  visibility = ['//aos/common:__pkg__'],
   srcs = [
     'condition.cc',
   ],
   deps = [
     ':mutex',
-    '//aos/common:condition',
+    '//aos/common:real_condition',
     ':aos_sync',
     '//aos/common/logging:logging_interface',
   ],
@@ -151,12 +152,13 @@
 
 cc_library(
   name = 'event',
+  visibility = ['//aos/common:__pkg__'],
   srcs = [
     'event.cc',
   ],
   deps = [
     ':aos_sync',
     '//aos/common/logging:logging_interface',
-    '//aos/common:event',
+    '//aos/common:real_event',
   ],
 )
diff --git a/aos/linux_code/ipc_lib/event.cc b/aos/linux_code/ipc_lib/event.cc
index e95b45e..ae32d39 100644
--- a/aos/linux_code/ipc_lib/event.cc
+++ b/aos/linux_code/ipc_lib/event.cc
@@ -20,6 +20,18 @@
   PLOG(FATAL, "futex_wait(%p) failed", &impl_);
 }
 
+bool Event::WaitTimeout(const ::aos::time::Time &timeout) {
+  const auto timeout_timespec = timeout.ToTimespec();
+  int ret;
+  do {
+    ret = futex_wait_timeout(&impl_, &timeout_timespec);
+  } while (ret == 1);
+  if (ret == 0) return true;
+  if (ret == 2) return false;
+  CHECK_EQ(-1, ret);
+  PLOG(FATAL, "futex_wait(%p) failed", &impl_);
+}
+
 // We're not going to expose the number woken because that's not easily portable
 // to condition variable-based implementations.
 void Event::Set() {
diff --git a/aos/linux_code/queue-tmpl.h b/aos/linux_code/queue-tmpl.h
index 25eb8d9..1362515 100644
--- a/aos/linux_code/queue-tmpl.h
+++ b/aos/linux_code/queue-tmpl.h
@@ -102,6 +102,7 @@
 T *Queue<T>::MakeRawMessage() {
   T *ret = static_cast<T *>(queue_->GetMessage());
   assert(ret != NULL);
+  ret->Zero();
   return ret;
 }
 
@@ -109,7 +110,6 @@
 aos::MessageBuilder<T> Queue<T>::MakeWithBuilder() {
   Init();
   T *const ret = MakeRawMessage();
-  ret->Zero();
   return aos::MessageBuilder<T>(queue_, ret);
 }
 
diff --git a/tools/bazel.rc b/tools/bazel.rc
index 1b77288..5ea0fcf 100644
--- a/tools/bazel.rc
+++ b/tools/bazel.rc
@@ -9,6 +9,8 @@
 # TODO(Brian): Fix Bazel so this actually does something again...
 build --hdrs_check=strict
 
+build --crosstool_top=//tools/cpp:toolchain
+
 # Show paths to a few more than just 1 target.
 build --show_result 15
 # Dump the output of the failing test to stdout.