Merge "Move ReadSctpMessage to a class"
diff --git a/aos/aos_cli_utils.cc b/aos/aos_cli_utils.cc
index e36c3d2..84ba1e4 100644
--- a/aos/aos_cli_utils.cc
+++ b/aos/aos_cli_utils.cc
@@ -32,7 +32,8 @@
bool CliUtilInfo::Initialize(
int *argc, char ***argv,
- std::function<bool(const aos::Channel *)> channel_filter) {
+ std::function<bool(const aos::Channel *)> channel_filter,
+ bool expect_args) {
// Don't generate failure output if the config doesn't exist while attempting
// to autocomplete.
if (struct stat file_stat;
@@ -44,66 +45,76 @@
return true;
}
- std::string channel_name;
- std::string message_type;
- if (*argc > 1) {
- channel_name = (*argv)[1];
- ShiftArgs(argc, argv);
- }
- if (*argc > 1) {
- message_type = (*argv)[1];
- ShiftArgs(argc, argv);
- }
-
config.emplace(aos::configuration::ReadConfig(FLAGS_config));
event_loop.emplace(&config->message());
event_loop->SkipTimingReport();
event_loop->SkipAosLog();
- if (FLAGS__bash_autocomplete) {
- Autocomplete(channel_name, message_type, channel_filter);
- return true;
- }
-
- const flatbuffers::Vector<flatbuffers::Offset<aos::Channel>> *const channels =
+ const flatbuffers::Vector<flatbuffers::Offset<aos::Channel>> *channels =
event_loop->configuration()->channels();
- if (channel_name.empty() && message_type.empty()) {
- std::cout << "Channels:\n";
+
+ do {
+ std::string channel_name;
+ std::string message_type;
+ if (*argc > 1) {
+ channel_name = (*argv)[1];
+ ShiftArgs(argc, argv);
+ }
+ if (*argc > 1) {
+ message_type = (*argv)[1];
+ ShiftArgs(argc, argv);
+ }
+
+ if (FLAGS__bash_autocomplete) {
+ Autocomplete(channel_name, message_type, channel_filter);
+ return true;
+ }
+
+ if (channel_name.empty() && message_type.empty()) {
+ std::cout << "Channels:\n";
+ for (const aos::Channel *channel : *channels) {
+ if (FLAGS_all || channel_filter(channel)) {
+ std::cout << channel->name()->c_str() << ' '
+ << channel->type()->c_str() << '\n';
+ }
+ }
+ return true;
+ }
+
+ std::vector<const aos::Channel *> found_channels_now;
+ bool found_exact = false;
for (const aos::Channel *channel : *channels) {
- if (FLAGS_all || channel_filter(channel)) {
- std::cout << channel->name()->c_str() << ' ' << channel->type()->c_str()
- << '\n';
+ if (!FLAGS_all && !channel_filter(channel)) {
+ continue;
}
- }
- return true;
- }
-
- bool found_exact = false;
- for (const aos::Channel *channel : *channels) {
- if (!FLAGS_all && !channel_filter(channel)) {
- continue;
- }
- if (channel->name()->c_str() != channel_name) {
- continue;
- }
- if (channel->type()->string_view() == message_type) {
- if (!found_exact) {
- found_channels.clear();
- found_exact = true;
+ if (channel->name()->c_str() != channel_name) {
+ continue;
}
- } else if (!found_exact && channel->type()->string_view().find(
- message_type) != std::string_view::npos) {
- } else {
- continue;
+ if (channel->type()->string_view() == message_type) {
+ if (!found_exact) {
+ found_channels_now.clear();
+ found_exact = true;
+ }
+ } else if (!found_exact && channel->type()->string_view().find(
+ message_type) != std::string_view::npos) {
+ } else {
+ continue;
+ }
+ found_channels_now.push_back(channel);
}
- found_channels.push_back(channel);
- }
- if (found_channels.empty()) {
- LOG(FATAL) << "Could not find any channels with the given name and type.";
- } else if (found_channels.size() > 1 && !message_type.empty()) {
- LOG(FATAL) << "Multiple channels found with same type";
- }
+ if (found_channels_now.empty()) {
+ LOG(FATAL)
+ << "Could not find any channels with the given name and type for "
+ << channel_name << " " << message_type;
+ } else if (found_channels_now.size() > 1 && !message_type.empty()) {
+ LOG(FATAL) << "Multiple channels found with same type for "
+ << channel_name << " " << message_type;
+ }
+ for (const aos::Channel *channel : found_channels_now) {
+ found_channels.push_back(channel);
+ }
+ } while (expect_args && *argc > 1);
return false;
}
diff --git a/aos/aos_cli_utils.h b/aos/aos_cli_utils.h
index e158737..962e0a0 100644
--- a/aos/aos_cli_utils.h
+++ b/aos/aos_cli_utils.h
@@ -13,7 +13,8 @@
// If this returns false, the other fields will be filled out appropriately.
// event_loop will be filled out before channel_filter is called.
bool Initialize(int *argc, char ***argv,
- std::function<bool(const aos::Channel *)> channel_filter);
+ std::function<bool(const aos::Channel *)> channel_filter,
+ bool expect_args);
std::optional<aos::FlatbufferDetachedBuffer<aos::Configuration>> config;
std::optional<aos::ShmEventLoop> event_loop;
diff --git a/aos/aos_dump.cc b/aos/aos_dump.cc
index e2467b3..477b6fb 100644
--- a/aos/aos_dump.cc
+++ b/aos/aos_dump.cc
@@ -70,11 +70,13 @@
aos::InitGoogle(&argc, &argv);
aos::CliUtilInfo cli_info;
- if (cli_info.Initialize(&argc, &argv,
- [&cli_info](const aos::Channel *channel) {
- return aos::configuration::ChannelIsReadableOnNode(
- channel, cli_info.event_loop->node());
- })) {
+ if (cli_info.Initialize(
+ &argc, &argv,
+ [&cli_info](const aos::Channel *channel) {
+ return aos::configuration::ChannelIsReadableOnNode(
+ channel, cli_info.event_loop->node());
+ },
+ true)) {
return 0;
}
diff --git a/aos/aos_send.cc b/aos/aos_send.cc
index d94418a..91ffb1c 100644
--- a/aos/aos_send.cc
+++ b/aos/aos_send.cc
@@ -19,11 +19,13 @@
aos::InitGoogle(&argc, &argv);
aos::CliUtilInfo cli_info;
- if (cli_info.Initialize(&argc, &argv,
- [&cli_info](const aos::Channel *channel) {
- return aos::configuration::ChannelIsSendableOnNode(
- channel, cli_info.event_loop->node());
- })) {
+ if (cli_info.Initialize(
+ &argc, &argv,
+ [&cli_info](const aos::Channel *channel) {
+ return aos::configuration::ChannelIsSendableOnNode(
+ channel, cli_info.event_loop->node());
+ },
+ false)) {
return 0;
}
if (cli_info.found_channels.size() > 1) {
diff --git a/aos/realtime.cc b/aos/realtime.cc
index cd9ea43..dc53a37 100644
--- a/aos/realtime.cc
+++ b/aos/realtime.cc
@@ -36,6 +36,12 @@
int MallocHook_AddDeleteHook(MallocHook_DeleteHook hook) __attribute__((weak));
int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook hook)
__attribute__((weak));
+
+// Declare tc_malloc weak so we can check if it exists.
+void *tc_malloc(size_t size) __attribute__((weak));
+
+void *__libc_malloc(size_t size);
+void __libc_free(void *ptr);
} // extern "C"
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead {
@@ -251,17 +257,57 @@
}
}
+extern "C" {
+
+// malloc hooks for libc. Tcmalloc will replace everything it finds (malloc,
+// __libc_malloc, etc.), so we need its specific hook above as well.
+void *aos_malloc_hook(size_t size) {
+ if (FLAGS_die_on_malloc && aos::is_realtime) {
+ aos::is_realtime = false;
+ RAW_LOG(FATAL, "Malloced %zu bytes", size);
+ return nullptr;
+ } else {
+ return __libc_malloc(size);
+ }
+}
+
+void aos_free_hook(void *ptr) {
+ if (FLAGS_die_on_malloc && aos::is_realtime && ptr != nullptr) {
+ aos::is_realtime = false;
+ RAW_LOG(FATAL, "Deleted %p", ptr);
+ } else {
+ __libc_free(ptr);
+ }
+}
+
+void *malloc(size_t size) __attribute__((weak, alias("aos_malloc_hook")));
+void free(void *ptr) __attribute__((weak, alias("aos_free_hook")));
+
+}
+
void RegisterMallocHook() {
if (FLAGS_die_on_malloc) {
- if (&MallocHook_AddNewHook != nullptr) {
- CHECK(MallocHook_AddNewHook(&NewHook));
+ // tcmalloc redefines __libc_malloc, so use this as a feature test.
+ if (&__libc_malloc == &tc_malloc) {
+ RAW_LOG(INFO, "Hooking tcmalloc for die_on_malloc");
+ if (&MallocHook_AddNewHook != nullptr) {
+ CHECK(MallocHook_AddNewHook(&NewHook));
+ } else {
+ has_malloc_hook = false;
+ }
+ if (&MallocHook_AddDeleteHook != nullptr) {
+ CHECK(MallocHook_AddDeleteHook(&DeleteHook));
+ } else {
+ has_malloc_hook = false;
+ }
} else {
- has_malloc_hook = false;
- }
- if (&MallocHook_AddDeleteHook != nullptr) {
- CHECK(MallocHook_AddDeleteHook(&DeleteHook));
- } else {
- has_malloc_hook = false;
+ RAW_LOG(INFO, "Replacing glibc malloc");
+ if (&malloc != &aos_malloc_hook) {
+ has_malloc_hook = false;
+ }
+ if (&free != &aos_free_hook) {
+ has_malloc_hook = false;
+ }
}
}
}