Merge "Make lockless_queue_death_test work on aarch64"
diff --git a/aos/configuration.cc b/aos/configuration.cc
index bc7182c..580c2e0 100644
--- a/aos/configuration.cc
+++ b/aos/configuration.cc
@@ -610,6 +610,9 @@
 
       auto result = applications.insert(RecursiveCopyFlatBuffer(a));
       if (!result.second) {
+        if (a->has_args()) {
+          result.first->mutable_message()->clear_args();
+        }
         *result.first =
             MergeFlatBuffers(*result.first, RecursiveCopyFlatBuffer(a));
       }
diff --git a/aos/events/event_loop_event.h b/aos/events/event_loop_event.h
index 808a4fe..a86f670 100644
--- a/aos/events/event_loop_event.h
+++ b/aos/events/event_loop_event.h
@@ -32,7 +32,7 @@
   }
   void set_generation(size_t generation) { generation_ = generation; }
 
-  virtual void HandleEvent() = 0;
+  virtual void HandleEvent() noexcept = 0;
 
  private:
   monotonic_clock::time_point event_time_ = monotonic_clock::max_time;
@@ -45,7 +45,7 @@
  public:
   EventHandler(T *t) : t_(t) {}
   ~EventHandler() override = default;
-  void HandleEvent() override { t_->HandleEvent(); }
+  void HandleEvent() noexcept override { t_->HandleEvent(); }
 
  private:
   T *const t_;
diff --git a/aos/events/event_loop_param_test.cc b/aos/events/event_loop_param_test.cc
index 30e293d..fca25d4 100644
--- a/aos/events/event_loop_param_test.cc
+++ b/aos/events/event_loop_param_test.cc
@@ -1186,14 +1186,14 @@
   auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
 
   monotonic_clock::time_point s = loop->monotonic_now();
-  test_timer->Setup(s, ::std::chrono::milliseconds(70));
-  ender_timer->Setup(s + ::std::chrono::milliseconds(200));
-  EndEventLoop(loop.get(), ::std::chrono::milliseconds(350));
+  test_timer->Setup(s, ::std::chrono::milliseconds(500));
+  ender_timer->Setup(s + ::std::chrono::milliseconds(1250));
+  EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
   Run();
 
   EXPECT_THAT(iteration_list,
-              ::testing::ElementsAre(s, s + chrono::milliseconds(70),
-                                     s + chrono::milliseconds(140)));
+              ::testing::ElementsAre(s, s + chrono::milliseconds(500),
+                                     s + chrono::milliseconds(1000)));
 }
 
 // Verify that a timer can disable itself.
diff --git a/aos/events/logging/log_namer.h b/aos/events/logging/log_namer.h
index f1f1829..00e1856 100644
--- a/aos/events/logging/log_namer.h
+++ b/aos/events/logging/log_namer.h
@@ -106,8 +106,8 @@
 
   monotonic_clock::time_point monotonic_start_time_ = monotonic_clock::min_time;
 
-  const Node *const node_ = nullptr;
-  const size_t node_index_ = 0;
+  const Node *node_ = nullptr;
+  size_t node_index_ = 0;
   LogNamer *log_namer_;
   UUID parts_uuid_ = UUID::Random();
   size_t parts_index_ = 0;
diff --git a/aos/events/logging/log_reader.h b/aos/events/logging/log_reader.h
index e367f0c..5cccdeb 100644
--- a/aos/events/logging/log_reader.h
+++ b/aos/events/logging/log_reader.h
@@ -163,6 +163,14 @@
                                      true) != nullptr;
   }
 
+  template <typename T>
+  void MaybeRemapLoggedChannel(std::string_view name,
+                               const Node *node = nullptr) {
+    if (HasChannel<T>(name, node)) {
+      RemapLoggedChannel<T>(name, node);
+    }
+  }
+
   // Returns true if the channel exists on the node and was logged.
   template <typename T>
   bool HasLoggedChannel(std::string_view name, const Node *node = nullptr) {
diff --git a/aos/events/logging/logger_test.cc b/aos/events/logging/logger_test.cc
index a1e8cc9..97b293a 100644
--- a/aos/events/logging/logger_test.cc
+++ b/aos/events/logging/logger_test.cc
@@ -2273,7 +2273,7 @@
 }
 
 // Test that renaming the base, renames the folder.
-TEST_F(MultinodeLoggerTest, LoggerRenameFolder) {
+TEST_P(MultinodeLoggerTest, LoggerRenameFolder) {
   util::UnlinkRecursive(tmp_dir_ + "/renamefolder");
   util::UnlinkRecursive(tmp_dir_ + "/new-good");
   time_converter_.AddMonotonic(
diff --git a/aos/events/simulated_event_loop.cc b/aos/events/simulated_event_loop.cc
index 083e246..a43cb30 100644
--- a/aos/events/simulated_event_loop.cc
+++ b/aos/events/simulated_event_loop.cc
@@ -127,7 +127,7 @@
 
   void Schedule(std::shared_ptr<SimulatedMessage> message);
 
-  void HandleEvent();
+  void HandleEvent() noexcept;
 
   void SetSimulatedChannel(SimulatedChannel *channel) {
     simulated_channel_ = channel;
@@ -153,9 +153,9 @@
       : channel_(channel),
         channel_storage_duration_(channel_storage_duration),
         next_queue_index_(ipc_lib::QueueIndex::Zero(number_buffers())) {
-    available_buffer_indices_.reserve(number_buffers());
+    available_buffer_indices_.resize(number_buffers());
     for (int i = 0; i < number_buffers(); ++i) {
-      available_buffer_indices_.push_back(i);
+      available_buffer_indices_[i] = i;
     }
   }
 
@@ -473,7 +473,7 @@
   void Setup(monotonic_clock::time_point base,
              monotonic_clock::duration repeat_offset) override;
 
-  void HandleEvent();
+  void HandleEvent() noexcept;
 
   void Disable() override;
 
@@ -496,7 +496,7 @@
                              const monotonic_clock::duration offset);
   ~SimulatedPhasedLoopHandler();
 
-  void HandleEvent();
+  void HandleEvent() noexcept;
 
   void Schedule(monotonic_clock::time_point sleep_time) override;
 
@@ -840,7 +840,7 @@
   msgs_.emplace_back(message);
 }
 
-void SimulatedWatcher::HandleEvent() {
+void SimulatedWatcher::HandleEvent() noexcept {
   const monotonic_clock::time_point monotonic_now =
       simulated_event_loop_->monotonic_now();
   VLOG(1) << simulated_event_loop_->distributed_now() << " "
@@ -1094,7 +1094,7 @@
   simulated_event_loop_->AddEvent(&event_);
 }
 
-void SimulatedTimerHandler::HandleEvent() {
+void SimulatedTimerHandler::HandleEvent() noexcept {
   const monotonic_clock::time_point monotonic_now =
       simulated_event_loop_->monotonic_now();
   VLOG(1) << simulated_event_loop_->distributed_now() << " "
@@ -1152,7 +1152,7 @@
   simulated_event_loop_->RemoveEvent(&event_);
 }
 
-void SimulatedPhasedLoopHandler::HandleEvent() {
+void SimulatedPhasedLoopHandler::HandleEvent() noexcept {
   monotonic_clock::time_point monotonic_now =
       simulated_event_loop_->monotonic_now();
   VLOG(1) << monotonic_now << " Phased loop " << simulated_event_loop_->name()
diff --git a/aos/network/message_bridge_server_lib.cc b/aos/network/message_bridge_server_lib.cc
index 41fb915..dbca3fb 100644
--- a/aos/network/message_bridge_server_lib.cc
+++ b/aos/network/message_bridge_server_lib.cc
@@ -194,14 +194,18 @@
 
 int ChannelState::NodeConnected(const Node *node, sctp_assoc_t assoc_id,
                                 int stream, SctpServer *server) {
-  VLOG(1) << "Connected to assoc_id: " << assoc_id;
+  VLOG(1) << "Connected to assoc_id: " << assoc_id << " for stream " << stream;
   for (ChannelState::Peer &peer : peers_) {
     if (peer.connection->name()->string_view() == node->name()->string_view()) {
       // There's a peer already connected.  Disconnect them and take over.
       if (peer.sac_assoc_id != 0) {
-        LOG(WARNING) << "Peer " << peer.sac_assoc_id
-                     << " already connected, aborting old connection.";
-        server->Abort(peer.sac_assoc_id);
+        if (peer.sac_assoc_id == assoc_id) {
+          LOG(WARNING) << "Reconnecting with the same ID, something got lost";
+        } else {
+          LOG(WARNING) << "Peer " << peer.sac_assoc_id
+                       << " already connected, aborting old connection.";
+          server->Abort(peer.sac_assoc_id);
+        }
       }
 
       peer.sac_assoc_id = assoc_id;
diff --git a/aos/util/file.cc b/aos/util/file.cc
index a11e330..4473d4d 100644
--- a/aos/util/file.cc
+++ b/aos/util/file.cc
@@ -7,6 +7,9 @@
 #include <unistd.h>
 
 #include <string_view>
+#if __has_feature(memory_sanitizer)
+#include <sanitizer/msan_interface.h>
+#endif
 
 #include "aos/scoped/scoped_fd.h"
 
@@ -101,6 +104,15 @@
   }
 
   while ((curr = fts_read(ftsp))) {
+#if __has_feature(memory_sanitizer)
+    // fts_read doesn't have propper msan interceptors.  Unpoison it ourselves.
+    if (curr) {
+      __msan_unpoison(curr, sizeof(*curr));
+      __msan_unpoison_string(curr->fts_accpath);
+      __msan_unpoison_string(curr->fts_path);
+      __msan_unpoison_string(curr->fts_name);
+    }
+#endif
     switch (curr->fts_info) {
       case FTS_NS:
       case FTS_DNR: