1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 // Copyright (c) 2005, Google Inc.
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // ---
32 // Author: Sanjay Ghemawat
33 // Chris Demetriou (refactoring)
34 //
35 // Profile current program by sampling stack-trace every so often
36
37 #include "config.h"
38 #include "getpc.h" // should be first to get the _GNU_SOURCE dfn
39 #include <signal.h>
40 #include <assert.h>
41 #include <stdio.h>
42 #include <errno.h>
43 #include <string.h>
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h> // for getpid()
46 #endif
47 #if defined(HAVE_SYS_UCONTEXT_H)
48 #include <sys/ucontext.h>
49 #elif defined(HAVE_UCONTEXT_H)
50 #include <ucontext.h>
51 #elif defined(HAVE_CYGWIN_SIGNAL_H)
52 #include <cygwin/signal.h>
53 typedef ucontext ucontext_t;
54 #else
55 typedef int ucontext_t; // just to quiet the compiler, mostly
56 #endif
57 #include <sys/time.h>
58 #include <string>
59 #include <gperftools/profiler.h>
60 #include <gperftools/stacktrace.h>
61 #include "base/commandlineflags.h"
62 #include "base/logging.h"
63 #include "base/googleinit.h"
64 #include "base/spinlock.h"
65 #include "base/sysinfo.h" /* for GetUniquePathFromEnv, etc */
66 #include "profiledata.h"
67 #include "profile-handler.h"
68 #ifdef HAVE_CONFLICT_SIGNAL_H
69 #include "conflict-signal.h" /* used on msvc machines */
70 #endif
71
72 using std::string;
73
74 DEFINE_bool(cpu_profiler_unittest,
75 EnvToBool("PERFTOOLS_UNITTEST", true),
76 "Determines whether or not we are running under the \
77 control of a unit test. This allows us to include or \
78 exclude certain behaviours.");
79
80 // Collects up all profile data. This is a singleton, which is
81 // initialized by a constructor at startup. If no cpu profiler
82 // signal is specified then the profiler lifecycle is either
83 // manaully controlled via the API or attached to the scope of
84 // the singleton (program scope). Otherwise the cpu toggle is
85 // used to allow for user selectable control via signal generation.
86 // This is very useful for profiling a daemon process without
87 // having to start and stop the daemon or having to modify the
88 // source code to use the cpu profiler API.
89 class CpuProfiler {
90 public:
91 CpuProfiler();
92 ~CpuProfiler();
93
94 // Start profiler to write profile info into fname
95 bool Start(const char* fname, const ProfilerOptions* options);
96
97 // Stop profiling and write the data to disk.
98 void Stop();
99
100 // Write the data to disk (and continue profiling).
101 void FlushTable();
102
103 bool Enabled();
104
105 void GetCurrentState(ProfilerState* state);
106
107 static CpuProfiler instance_;
108
109 private:
110 // This lock implements the locking requirements described in the ProfileData
111 // documentation, specifically:
112 //
113 // lock_ is held all over all collector_ method calls except for the 'Add'
114 // call made from the signal handler, to protect against concurrent use of
115 // collector_'s control routines. Code other than signal handler must
116 // unregister the signal handler before calling any collector_ method.
117 // 'Add' method in the collector is protected by a guarantee from
118 // ProfileHandle that only one instance of prof_handler can run at a time.
119 SpinLock lock_;
120 ProfileData collector_;
121
122 // Filter function and its argument, if any. (NULL means include all
123 // samples). Set at start, read-only while running. Written while holding
124 // lock_, read and executed in the context of SIGPROF interrupt.
125 int (*filter_)(void*);
126 void* filter_arg_;
127
128 // Opaque token returned by the profile handler. To be used when calling
129 // ProfileHandlerUnregisterCallback.
130 ProfileHandlerToken* prof_handler_token_;
131
132 // Sets up a callback to receive SIGPROF interrupt.
133 void EnableHandler();
134
135 // Disables receiving SIGPROF interrupt.
136 void DisableHandler();
137
138 // Signal handler that records the interrupted pc in the profile data.
139 static void prof_handler(int sig, siginfo_t*, void* signal_ucontext,
140 void* cpu_profiler);
141 };
142
143 // Signal handler that is registered when a user selectable signal
144 // number is defined in the environment variable CPUPROFILESIGNAL.
CpuProfilerSwitch(int signal_number)145 static void CpuProfilerSwitch(int signal_number)
146 {
147 bool static started = false;
148 static unsigned profile_count = 0;
149 static char base_profile_name[1024] = "\0";
150
151 if (base_profile_name[0] == '\0') {
152 if (!GetUniquePathFromEnv("CPUPROFILE", base_profile_name)) {
153 RAW_LOG(FATAL,"Cpu profiler switch is registered but no CPUPROFILE is defined");
154 return;
155 }
156 }
157 if (!started)
158 {
159 char full_profile_name[1024];
160
161 snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u",
162 base_profile_name, profile_count++);
163
164 if(!ProfilerStart(full_profile_name))
165 {
166 RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
167 full_profile_name, strerror(errno));
168 }
169 }
170 else
171 {
172 ProfilerStop();
173 }
174 started = !started;
175 }
176
177 // Profile data structure singleton: Constructor will check to see if
178 // profiling should be enabled. Destructor will write profile data
179 // out to disk.
180 CpuProfiler CpuProfiler::instance_;
181
182 // Initialize profiling: activated if getenv("CPUPROFILE") exists.
CpuProfiler()183 CpuProfiler::CpuProfiler()
184 : prof_handler_token_(NULL) {
185 // TODO(cgd) Move this code *out* of the CpuProfile constructor into a
186 // separate object responsible for initialization. With ProfileHandler there
187 // is no need to limit the number of profilers.
188 if (getenv("CPUPROFILE") == NULL) {
189 if (!FLAGS_cpu_profiler_unittest) {
190 RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n");
191 }
192 return;
193 }
194
195 // We don't enable profiling if setuid -- it's a security risk
196 #ifdef HAVE_GETEUID
197 if (getuid() != geteuid()) {
198 if (!FLAGS_cpu_profiler_unittest) {
199 RAW_LOG(WARNING, "Cannot perform CPU profiling when running with setuid\n");
200 }
201 return;
202 }
203 #endif
204
205 char *signal_number_str = getenv("CPUPROFILESIGNAL");
206 if (signal_number_str != NULL) {
207 long int signal_number = strtol(signal_number_str, NULL, 10);
208 if (signal_number >= 1 && signal_number <= 64) {
209 intptr_t old_signal_handler = reinterpret_cast<intptr_t>(signal(signal_number, CpuProfilerSwitch));
210 if (old_signal_handler == 0) {
211 RAW_LOG(INFO,"Using signal %d as cpu profiling switch", signal_number);
212 } else {
213 RAW_LOG(FATAL, "Signal %d already in use\n", signal_number);
214 }
215 } else {
216 RAW_LOG(FATAL, "Signal number %s is invalid\n", signal_number_str);
217 }
218 } else {
219 char fname[PATH_MAX];
220 if (!GetUniquePathFromEnv("CPUPROFILE", fname)) {
221 if (!FLAGS_cpu_profiler_unittest) {
222 RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n");
223 }
224 return;
225 }
226
227 if (!Start(fname, NULL)) {
228 RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
229 fname, strerror(errno));
230 }
231 }
232 }
233
Start(const char * fname,const ProfilerOptions * options)234 bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) {
235 SpinLockHolder cl(&lock_);
236
237 if (collector_.enabled()) {
238 return false;
239 }
240
241 ProfileHandlerState prof_handler_state;
242 ProfileHandlerGetState(&prof_handler_state);
243
244 ProfileData::Options collector_options;
245 collector_options.set_frequency(prof_handler_state.frequency);
246 if (!collector_.Start(fname, collector_options)) {
247 return false;
248 }
249
250 filter_ = NULL;
251 if (options != NULL && options->filter_in_thread != NULL) {
252 filter_ = options->filter_in_thread;
253 filter_arg_ = options->filter_in_thread_arg;
254 }
255
256 // Setup handler for SIGPROF interrupts
257 EnableHandler();
258
259 return true;
260 }
261
~CpuProfiler()262 CpuProfiler::~CpuProfiler() {
263 Stop();
264 }
265
266 // Stop profiling and write out any collected profile data
Stop()267 void CpuProfiler::Stop() {
268 SpinLockHolder cl(&lock_);
269
270 if (!collector_.enabled()) {
271 return;
272 }
273
274 // Unregister prof_handler to stop receiving SIGPROF interrupts before
275 // stopping the collector.
276 DisableHandler();
277
278 // DisableHandler waits for the currently running callback to complete and
279 // guarantees no future invocations. It is safe to stop the collector.
280 collector_.Stop();
281 }
282
FlushTable()283 void CpuProfiler::FlushTable() {
284 SpinLockHolder cl(&lock_);
285
286 if (!collector_.enabled()) {
287 return;
288 }
289
290 // Unregister prof_handler to stop receiving SIGPROF interrupts before
291 // flushing the profile data.
292 DisableHandler();
293
294 // DisableHandler waits for the currently running callback to complete and
295 // guarantees no future invocations. It is safe to flush the profile data.
296 collector_.FlushTable();
297
298 EnableHandler();
299 }
300
Enabled()301 bool CpuProfiler::Enabled() {
302 SpinLockHolder cl(&lock_);
303 return collector_.enabled();
304 }
305
GetCurrentState(ProfilerState * state)306 void CpuProfiler::GetCurrentState(ProfilerState* state) {
307 ProfileData::State collector_state;
308 {
309 SpinLockHolder cl(&lock_);
310 collector_.GetCurrentState(&collector_state);
311 }
312
313 state->enabled = collector_state.enabled;
314 state->start_time = static_cast<time_t>(collector_state.start_time);
315 state->samples_gathered = collector_state.samples_gathered;
316 int buf_size = sizeof(state->profile_name);
317 strncpy(state->profile_name, collector_state.profile_name, buf_size);
318 state->profile_name[buf_size-1] = '\0';
319 }
320
EnableHandler()321 void CpuProfiler::EnableHandler() {
322 RAW_CHECK(prof_handler_token_ == NULL, "SIGPROF handler already registered");
323 prof_handler_token_ = ProfileHandlerRegisterCallback(prof_handler, this);
324 RAW_CHECK(prof_handler_token_ != NULL, "Failed to set up SIGPROF handler");
325 }
326
DisableHandler()327 void CpuProfiler::DisableHandler() {
328 RAW_CHECK(prof_handler_token_ != NULL, "SIGPROF handler is not registered");
329 ProfileHandlerUnregisterCallback(prof_handler_token_);
330 prof_handler_token_ = NULL;
331 }
332
333 // Signal handler that records the pc in the profile-data structure. We do no
334 // synchronization here. profile-handler.cc guarantees that at most one
335 // instance of prof_handler() will run at a time. All other routines that
336 // access the data touched by prof_handler() disable this signal handler before
337 // accessing the data and therefore cannot execute concurrently with
338 // prof_handler().
prof_handler(int sig,siginfo_t *,void * signal_ucontext,void * cpu_profiler)339 void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext,
340 void* cpu_profiler) {
341 CpuProfiler* instance = static_cast<CpuProfiler*>(cpu_profiler);
342
343 if (instance->filter_ == NULL ||
344 (*instance->filter_)(instance->filter_arg_)) {
345 void* stack[ProfileData::kMaxStackDepth];
346
347 // Under frame-pointer-based unwinding at least on x86, the
348 // top-most active routine doesn't show up as a normal frame, but
349 // as the "pc" value in the signal handler context.
350 stack[0] = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
351
352 // We skip the top three stack trace entries (this function,
353 // SignalHandler::SignalHandler and one signal handler frame)
354 // since they are artifacts of profiling and should not be
355 // measured. Other profiling related frames may be removed by
356 // "pprof" at analysis time. Instead of skipping the top frames,
357 // we could skip nothing, but that would increase the profile size
358 // unnecessarily.
359 int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1,
360 3, signal_ucontext);
361
362 void **used_stack;
363 if (depth > 0 && stack[1] == stack[0]) {
364 // in case of non-frame-pointer-based unwinding we will get
365 // duplicate of PC in stack[1], which we don't want
366 used_stack = stack + 1;
367 } else {
368 used_stack = stack;
369 depth++; // To account for pc value in stack[0];
370 }
371
372 instance->collector_.Add(depth, used_stack);
373 }
374 }
375
376 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
377
ProfilerRegisterThread()378 extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() {
379 ProfileHandlerRegisterThread();
380 }
381
ProfilerFlush()382 extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() {
383 CpuProfiler::instance_.FlushTable();
384 }
385
ProfilingIsEnabledForAllThreads()386 extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() {
387 return CpuProfiler::instance_.Enabled();
388 }
389
ProfilerStart(const char * fname)390 extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) {
391 return CpuProfiler::instance_.Start(fname, NULL);
392 }
393
ProfilerStartWithOptions(const char * fname,const ProfilerOptions * options)394 extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(
395 const char *fname, const ProfilerOptions *options) {
396 return CpuProfiler::instance_.Start(fname, options);
397 }
398
ProfilerStop()399 extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() {
400 CpuProfiler::instance_.Stop();
401 }
402
ProfilerGetCurrentState(ProfilerState * state)403 extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(
404 ProfilerState* state) {
405 CpuProfiler::instance_.GetCurrentState(state);
406 }
407
408 #else // OS_CYGWIN
409
410 // ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't
411 // work as well for profiling, and also interferes with alarm(). Because of
412 // these issues, unless a specific need is identified, profiler support is
413 // disabled under Cygwin.
ProfilerRegisterThread()414 extern "C" void ProfilerRegisterThread() { }
ProfilerFlush()415 extern "C" void ProfilerFlush() { }
ProfilingIsEnabledForAllThreads()416 extern "C" int ProfilingIsEnabledForAllThreads() { return 0; }
ProfilerStart(const char * fname)417 extern "C" int ProfilerStart(const char* fname) { return 0; }
ProfilerStartWithOptions(const char * fname,const ProfilerOptions * options)418 extern "C" int ProfilerStartWithOptions(const char *fname,
419 const ProfilerOptions *options) {
420 return 0;
421 }
ProfilerStop()422 extern "C" void ProfilerStop() { }
ProfilerGetCurrentState(ProfilerState * state)423 extern "C" void ProfilerGetCurrentState(ProfilerState* state) {
424 memset(state, 0, sizeof(*state));
425 }
426
427 #endif // OS_CYGWIN
428
429 // DEPRECATED routines
ProfilerEnable()430 extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { }
ProfilerDisable()431 extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { }
432