]>
Commit | Line | Data |
---|---|---|
1e80ce41 | 1 | //===-- sanitizer_common_libcdep.cc ---------------------------------------===// |
2 | // | |
3 | // This file is distributed under the University of Illinois Open Source | |
4 | // License. See LICENSE.TXT for details. | |
5 | // | |
6 | //===----------------------------------------------------------------------===// | |
7 | // | |
8 | // This file is shared between AddressSanitizer and ThreadSanitizer | |
9 | // run-time libraries. | |
10 | //===----------------------------------------------------------------------===// | |
11 | ||
23e39437 | 12 | #include "sanitizer_allocator_interface.h" |
d2ef4bee | 13 | #include "sanitizer_common.h" |
7d752f28 | 14 | #include "sanitizer_flags.h" |
36093749 | 15 | #include "sanitizer_procmaps.h" |
1e80ce41 | 16 | |
5645a48f | 17 | |
1e80ce41 | 18 | namespace __sanitizer { |
19 | ||
5645a48f | 20 | static void (*SoftRssLimitExceededCallback)(bool exceeded); |
21 | void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) { | |
22 | CHECK_EQ(SoftRssLimitExceededCallback, nullptr); | |
23 | SoftRssLimitExceededCallback = Callback; | |
24 | } | |
25 | ||
23e39437 | 26 | #if SANITIZER_LINUX && !SANITIZER_GO |
d2ef4bee | 27 | // Weak default implementation for when sanitizer_stackdepot is not linked in. |
28 | SANITIZER_WEAK_ATTRIBUTE StackDepotStats *StackDepotGetStats() { | |
29 | return nullptr; | |
30 | } | |
31 | ||
5645a48f | 32 | void BackgroundThread(void *arg) { |
d2ef4bee | 33 | const uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb; |
34 | const uptr soft_rss_limit_mb = common_flags()->soft_rss_limit_mb; | |
35 | const bool heap_profile = common_flags()->heap_profile; | |
5645a48f | 36 | uptr prev_reported_rss = 0; |
37 | uptr prev_reported_stack_depot_size = 0; | |
38 | bool reached_soft_rss_limit = false; | |
23e39437 | 39 | uptr rss_during_last_reported_profile = 0; |
5645a48f | 40 | while (true) { |
41 | SleepForMillis(100); | |
d2ef4bee | 42 | const uptr current_rss_mb = GetRSS() >> 20; |
5645a48f | 43 | if (Verbosity()) { |
44 | // If RSS has grown 10% since last time, print some information. | |
45 | if (prev_reported_rss * 11 / 10 < current_rss_mb) { | |
46 | Printf("%s: RSS: %zdMb\n", SanitizerToolName, current_rss_mb); | |
47 | prev_reported_rss = current_rss_mb; | |
48 | } | |
49 | // If stack depot has grown 10% since last time, print it too. | |
50 | StackDepotStats *stack_depot_stats = StackDepotGetStats(); | |
d2ef4bee | 51 | if (stack_depot_stats) { |
52 | if (prev_reported_stack_depot_size * 11 / 10 < | |
53 | stack_depot_stats->allocated) { | |
54 | Printf("%s: StackDepot: %zd ids; %zdM allocated\n", | |
55 | SanitizerToolName, | |
56 | stack_depot_stats->n_uniq_ids, | |
57 | stack_depot_stats->allocated >> 20); | |
58 | prev_reported_stack_depot_size = stack_depot_stats->allocated; | |
59 | } | |
5645a48f | 60 | } |
61 | } | |
62 | // Check RSS against the limit. | |
63 | if (hard_rss_limit_mb && hard_rss_limit_mb < current_rss_mb) { | |
64 | Report("%s: hard rss limit exhausted (%zdMb vs %zdMb)\n", | |
65 | SanitizerToolName, hard_rss_limit_mb, current_rss_mb); | |
66 | DumpProcessMap(); | |
67 | Die(); | |
68 | } | |
69 | if (soft_rss_limit_mb) { | |
70 | if (soft_rss_limit_mb < current_rss_mb && !reached_soft_rss_limit) { | |
71 | reached_soft_rss_limit = true; | |
72 | Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n", | |
73 | SanitizerToolName, soft_rss_limit_mb, current_rss_mb); | |
74 | if (SoftRssLimitExceededCallback) | |
75 | SoftRssLimitExceededCallback(true); | |
76 | } else if (soft_rss_limit_mb >= current_rss_mb && | |
77 | reached_soft_rss_limit) { | |
78 | reached_soft_rss_limit = false; | |
79 | if (SoftRssLimitExceededCallback) | |
80 | SoftRssLimitExceededCallback(false); | |
81 | } | |
82 | } | |
23e39437 | 83 | if (heap_profile && |
84 | current_rss_mb > rss_during_last_reported_profile * 1.1) { | |
85 | Printf("\n\nHEAP PROFILE at RSS %zdMb\n", current_rss_mb); | |
36093749 | 86 | __sanitizer_print_memory_profile(90, 20); |
23e39437 | 87 | rss_during_last_reported_profile = current_rss_mb; |
88 | } | |
5645a48f | 89 | } |
90 | } | |
23e39437 | 91 | #endif |
92 | ||
93 | void WriteToSyslog(const char *msg) { | |
94 | InternalScopedString msg_copy(kErrorMessageBufferSize); | |
95 | msg_copy.append("%s", msg); | |
96 | char *p = msg_copy.data(); | |
97 | char *q; | |
98 | ||
99 | // Print one line at a time. | |
100 | // syslog, at least on Android, has an implicit message length limit. | |
d2ef4bee | 101 | while ((q = internal_strchr(p, '\n'))) { |
102 | *q = '\0'; | |
103 | WriteOneLineToSyslog(p); | |
104 | p = q + 1; | |
105 | } | |
106 | // Print remaining characters, if there are any. | |
107 | // Note that this will add an extra newline at the end. | |
108 | // FIXME: buffer extra output. This would need a thread-local buffer, which | |
109 | // on Android requires plugging into the tools (ex. ASan's) Thread class. | |
110 | if (*p) | |
23e39437 | 111 | WriteOneLineToSyslog(p); |
23e39437 | 112 | } |
5645a48f | 113 | |
114 | void MaybeStartBackgroudThread() { | |
23e39437 | 115 | #if SANITIZER_LINUX && \ |
116 | !SANITIZER_GO // Need to implement/test on other platforms. | |
5645a48f | 117 | // Start the background thread if one of the rss limits is given. |
118 | if (!common_flags()->hard_rss_limit_mb && | |
23e39437 | 119 | !common_flags()->soft_rss_limit_mb && |
23e39437 | 120 | !common_flags()->heap_profile) return; |
5645a48f | 121 | if (!&real_pthread_create) return; // Can't spawn the thread anyway. |
122 | internal_start_thread(BackgroundThread, nullptr); | |
a9586c9c | 123 | #endif |
a9586c9c | 124 | } |
125 | ||
d2ef4bee | 126 | static void (*sandboxing_callback)(); |
127 | void SetSandboxingCallback(void (*f)()) { | |
128 | sandboxing_callback = f; | |
36093749 | 129 | } |
130 | ||
1e80ce41 | 131 | } // namespace __sanitizer |
a9586c9c | 132 | |
36093749 | 133 | SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify, |
134 | __sanitizer_sandbox_arguments *args) { | |
d2ef4bee | 135 | __sanitizer::PlatformPrepareForSandboxing(args); |
23e39437 | 136 | if (__sanitizer::sandboxing_callback) |
137 | __sanitizer::sandboxing_callback(); | |
a9586c9c | 138 | } |