blob: 00b7f3ce3fdbf0258b93fa353cb8558a6041417c [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/logging/context.h"
Austin Schuh044e18b2015-10-21 20:17:09 -07002
Alex Perrycb7da4b2019-08-28 19:35:56 -07003#ifndef _GNU_SOURCE
4#define _GNU_SOURCE /* See feature_test_macros(7) */
5#endif
6
Austin Schuh8d2e3fa2020-09-10 23:01:55 -07007#if __has_feature(memory_sanitizer)
8#include <sanitizer/msan_interface.h>
9#endif
Brian Silvermancb5da1f2015-12-05 22:19:58 -050010#include <sys/prctl.h>
Brian Silvermancb5da1f2015-12-05 22:19:58 -050011#include <unistd.h>
12
Stephan Pleines0960c262024-05-31 20:29:24 -070013#include <algorithm>
14#include <cstddef>
Tyler Chatowbf0609c2021-07-31 16:13:27 -070015#include <cstring>
Stephan Pleines0960c262024-05-31 20:29:24 -070016#include <limits>
17#include <optional>
18#include <ostream>
Brian Silvermancb5da1f2015-12-05 22:19:58 -050019#include <string>
20
Alex Perrycb7da4b2019-08-28 19:35:56 -070021extern char *program_invocation_name;
22extern char *program_invocation_short_name;
23
Philipp Schrader790cb542023-07-05 21:06:52 -070024#include "glog/logging.h"
25
Stephan Pleinesf63bde82024-01-13 15:59:33 -080026namespace aos::logging::internal {
Brian Silvermancb5da1f2015-12-05 22:19:58 -050027namespace {
28
29// TODO(brians): Differentiate between threads with the same name in the same
30// process.
31
32::std::string GetMyName() {
33 // The maximum number of characters that can make up a thread name.
34 // The docs are unclear if it can be 16 characters with no '\0', so we'll be
35 // safe by adding our own where necessary.
36 static const size_t kThreadNameLength = 16;
37
38 ::std::string process_name(program_invocation_short_name);
39
40 char thread_name_array[kThreadNameLength + 1];
41 if (prctl(PR_GET_NAME, thread_name_array) != 0) {
Austin Schuh56196432020-10-24 20:15:21 -070042 PLOG(FATAL) << "prctl(PR_GET_NAME, " << thread_name_array << ") failed";
Brian Silvermancb5da1f2015-12-05 22:19:58 -050043 }
Austin Schuh8d2e3fa2020-09-10 23:01:55 -070044#if __has_feature(memory_sanitizer)
45 // msan doesn't understand PR_GET_NAME, so help it along.
46 __msan_unpoison(thread_name_array, sizeof(thread_name_array));
47#endif
Brian Silvermancb5da1f2015-12-05 22:19:58 -050048 thread_name_array[sizeof(thread_name_array) - 1] = '\0';
49 ::std::string thread_name(thread_name_array);
50
51 // If the first bunch of characters are the same.
52 // We cut off comparing at the shorter of the 2 strings because one or the
53 // other often ends up cut off.
54 if (strncmp(thread_name.c_str(), process_name.c_str(),
55 ::std::min(thread_name.length(), process_name.length())) == 0) {
56 // This thread doesn't have an actual name.
57 return process_name;
58 }
59
60 return process_name + '.' + thread_name;
61}
62
Tyler Chatow5bc9d682022-02-25 21:27:16 -080063thread_local std::optional<Context> my_context;
Brian Silvermancb5da1f2015-12-05 22:19:58 -050064
65// True if we're going to delete the current Context object ASAP. The
66// reason for doing this instead of just deleting them is that tsan (at least)
67// doesn't like it when pthread_atfork handlers do complicated stuff and it's
68// not a great idea anyways.
Austin Schuhf7bfb652023-08-25 14:22:50 -070069thread_local bool delete_current_context(false);
Brian Silvermancb5da1f2015-12-05 22:19:58 -050070
71} // namespace
Austin Schuh044e18b2015-10-21 20:17:09 -070072
Austin Schuh56196432020-10-24 20:15:21 -070073Context::Context() : sequence(0) {}
Austin Schuh044e18b2015-10-21 20:17:09 -070074
Brian Silvermancb5da1f2015-12-05 22:19:58 -050075// Used in aos/linux_code/init.cc when a thread's name is changed.
76void ReloadThreadName() {
Tyler Chatow5bc9d682022-02-25 21:27:16 -080077 if (my_context.has_value()) {
Austin Schuhad9e5eb2021-11-19 20:33:55 -080078 my_context->ClearName();
79 }
80}
81
82void Context::ClearName() { name_size = std::numeric_limits<size_t>::max(); }
83
84std::string_view Context::MyName() {
85 if (name_size == std::numeric_limits<size_t>::max()) {
Brian Silvermancb5da1f2015-12-05 22:19:58 -050086 ::std::string my_name = GetMyName();
Austin Schuh7bb558e2023-08-30 20:50:51 -070087 CHECK_LE(my_name.size() + 1, sizeof(Context::name))
88 << ": process/thread name '" << my_name << "' is too long";
Austin Schuhad9e5eb2021-11-19 20:33:55 -080089 strcpy(name, my_name.c_str());
90 name_size = my_name.size();
Brian Silvermancb5da1f2015-12-05 22:19:58 -050091 }
Austin Schuhad9e5eb2021-11-19 20:33:55 -080092
93 return std::string_view(&name[0], name_size);
Brian Silvermancb5da1f2015-12-05 22:19:58 -050094}
95
96Context *Context::Get() {
97 if (__builtin_expect(delete_current_context, false)) {
Tyler Chatow5bc9d682022-02-25 21:27:16 -080098 my_context.reset();
Brian Silvermancb5da1f2015-12-05 22:19:58 -050099 delete_current_context = false;
100 }
Tyler Chatow5bc9d682022-02-25 21:27:16 -0800101 if (__builtin_expect(!my_context.has_value(), false)) {
102 my_context.emplace();
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800103 my_context->ClearName();
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500104 my_context->source = getpid();
105 }
Tyler Chatow5bc9d682022-02-25 21:27:16 -0800106 return &*my_context;
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500107}
108
Austin Schuh8d2e3fa2020-09-10 23:01:55 -0700109void Context::Delete() { delete_current_context = true; }
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500110
Austin Schuha0c41ba2020-09-10 22:59:14 -0700111void Context::DeleteNow() {
Tyler Chatow5bc9d682022-02-25 21:27:16 -0800112 my_context.reset();
Austin Schuha0c41ba2020-09-10 22:59:14 -0700113 delete_current_context = false;
114}
115
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800116} // namespace aos::logging::internal