blob: 0aa3e7128ecb988a3ba6e2dd4c6abfb5900578bc [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
Austin Schuh044e18b2015-10-21 20:17:09 -070010#include <string.h>
Brian Silvermancb5da1f2015-12-05 22:19:58 -050011#include <sys/prctl.h>
12#include <sys/types.h>
13#include <unistd.h>
Brian Silverman1463c092020-10-30 17:28:24 -070014#include <errno.h>
Brian Silvermancb5da1f2015-12-05 22:19:58 -050015
16#include <string>
17
Alex Perrycb7da4b2019-08-28 19:35:56 -070018extern char *program_invocation_name;
19extern char *program_invocation_short_name;
20
Brian Silverman1463c092020-10-30 17:28:24 -070021#include "glog/logging.h"
22
John Park398c74a2018-10-20 21:17:39 -070023#include "aos/complex_thread_local.h"
Austin Schuh8d2e3fa2020-09-10 23:01:55 -070024#include "aos/die.h"
Austin Schuha0c41ba2020-09-10 22:59:14 -070025#include "aos/logging/implementations.h"
Brian Silvermanb47f5552020-10-01 15:08:14 -070026#include "aos/thread_local.h"
Austin Schuh044e18b2015-10-21 20:17:09 -070027
28namespace aos {
29namespace logging {
30namespace internal {
Brian Silvermancb5da1f2015-12-05 22:19:58 -050031namespace {
32
33// TODO(brians): Differentiate between threads with the same name in the same
34// process.
35
36::std::string GetMyName() {
37 // The maximum number of characters that can make up a thread name.
38 // The docs are unclear if it can be 16 characters with no '\0', so we'll be
39 // safe by adding our own where necessary.
40 static const size_t kThreadNameLength = 16;
41
42 ::std::string process_name(program_invocation_short_name);
43
44 char thread_name_array[kThreadNameLength + 1];
45 if (prctl(PR_GET_NAME, thread_name_array) != 0) {
Austin Schuh56196432020-10-24 20:15:21 -070046 PLOG(FATAL) << "prctl(PR_GET_NAME, " << thread_name_array << ") failed";
Brian Silvermancb5da1f2015-12-05 22:19:58 -050047 }
Austin Schuh8d2e3fa2020-09-10 23:01:55 -070048#if __has_feature(memory_sanitizer)
49 // msan doesn't understand PR_GET_NAME, so help it along.
50 __msan_unpoison(thread_name_array, sizeof(thread_name_array));
51#endif
Brian Silvermancb5da1f2015-12-05 22:19:58 -050052 thread_name_array[sizeof(thread_name_array) - 1] = '\0';
53 ::std::string thread_name(thread_name_array);
54
55 // If the first bunch of characters are the same.
56 // We cut off comparing at the shorter of the 2 strings because one or the
57 // other often ends up cut off.
58 if (strncmp(thread_name.c_str(), process_name.c_str(),
59 ::std::min(thread_name.length(), process_name.length())) == 0) {
60 // This thread doesn't have an actual name.
61 return process_name;
62 }
63
64 return process_name + '.' + thread_name;
65}
66
67::aos::ComplexThreadLocal<Context> my_context;
68
69// True if we're going to delete the current Context object ASAP. The
70// reason for doing this instead of just deleting them is that tsan (at least)
71// doesn't like it when pthread_atfork handlers do complicated stuff and it's
72// not a great idea anyways.
Brian Silvermanb47f5552020-10-01 15:08:14 -070073AOS_THREAD_LOCAL bool delete_current_context(false);
Brian Silvermancb5da1f2015-12-05 22:19:58 -050074
75} // namespace
Austin Schuh044e18b2015-10-21 20:17:09 -070076
Austin Schuh56196432020-10-24 20:15:21 -070077Context::Context() : sequence(0) {}
Austin Schuh044e18b2015-10-21 20:17:09 -070078
Brian Silvermancb5da1f2015-12-05 22:19:58 -050079// Used in aos/linux_code/init.cc when a thread's name is changed.
80void ReloadThreadName() {
81 if (my_context.created()) {
82 ::std::string my_name = GetMyName();
83 if (my_name.size() + 1 > sizeof(Context::name)) {
Austin Schuh8d2e3fa2020-09-10 23:01:55 -070084 Die("logging: process/thread name '%s' is too long\n", my_name.c_str());
Brian Silvermancb5da1f2015-12-05 22:19:58 -050085 }
86 strcpy(my_context->name, my_name.c_str());
87 my_context->name_size = my_name.size();
88 }
89}
90
91Context *Context::Get() {
92 if (__builtin_expect(delete_current_context, false)) {
93 my_context.Clear();
94 delete_current_context = false;
95 }
96 if (__builtin_expect(!my_context.created(), false)) {
97 my_context.Create();
98 ReloadThreadName();
99 my_context->source = getpid();
100 }
101 return my_context.get();
102}
103
Austin Schuh8d2e3fa2020-09-10 23:01:55 -0700104void Context::Delete() { delete_current_context = true; }
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500105
Austin Schuha0c41ba2020-09-10 22:59:14 -0700106void Context::DeleteNow() {
107 my_context.Clear();
108 delete_current_context = false;
109}
110
Austin Schuh044e18b2015-10-21 20:17:09 -0700111} // namespace internal
112} // namespace logging
113} // namespace aos