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 
69 using std::string;
70 
71 DEFINE_bool(cpu_profiler_unittest,
72             EnvToBool("PERFTOOLS_UNITTEST", true),
73             "Determines whether or not we are running under the \
74              control of a unit test. This allows us to include or \
75 			 exclude certain behaviours.");
76 
77 // Collects up all profile data. This is a singleton, which is
78 // initialized by a constructor at startup. If no cpu profiler
79 // signal is specified then the profiler lifecycle is either
80 // manaully controlled via the API or attached to the scope of
81 // the singleton (program scope). Otherwise the cpu toggle is
82 // used to allow for user selectable control via signal generation.
83 // This is very useful for profiling a daemon process without
84 // having to start and stop the daemon or having to modify the
85 // source code to use the cpu profiler API.
86 class CpuProfiler {
87  public:
88   CpuProfiler();
89   ~CpuProfiler();
90 
91   // Start profiler to write profile info into fname
92   bool Start(const char* fname, const ProfilerOptions* options);
93 
94   // Stop profiling and write the data to disk.
95   void Stop();
96 
97   // Write the data to disk (and continue profiling).
98   void FlushTable();
99 
100   bool Enabled();
101 
102   void GetCurrentState(ProfilerState* state);
103 
104   static CpuProfiler instance_;
105 
106  private:
107   // This lock implements the locking requirements described in the ProfileData
108   // documentation, specifically:
109   //
110   // lock_ is held all over all collector_ method calls except for the 'Add'
111   // call made from the signal handler, to protect against concurrent use of
112   // collector_'s control routines. Code other than signal handler must
113   // unregister the signal handler before calling any collector_ method.
114   // 'Add' method in the collector is protected by a guarantee from
115   // ProfileHandle that only one instance of prof_handler can run at a time.
116   SpinLock      lock_;
117   ProfileData   collector_;
118 
119   // Filter function and its argument, if any.  (NULL means include all
120   // samples).  Set at start, read-only while running.  Written while holding
121   // lock_, read and executed in the context of SIGPROF interrupt.
122   int           (*filter_)(void*);
123   void*         filter_arg_;
124 
125   // Opaque token returned by the profile handler. To be used when calling
126   // ProfileHandlerUnregisterCallback.
127   ProfileHandlerToken* prof_handler_token_;
128 
129   // Sets up a callback to receive SIGPROF interrupt.
130   void EnableHandler();
131 
132   // Disables receiving SIGPROF interrupt.
133   void DisableHandler();
134 
135   // Signal handler that records the interrupted pc in the profile data.
136   static void prof_handler(int sig, siginfo_t*, void* signal_ucontext,
137                            void* cpu_profiler);
138 };
139 
140 // Signal handler that is registered when a user selectable signal
141 // number is defined in the environment variable CPUPROFILESIGNAL.
CpuProfilerSwitch(int signal_number)142 static void CpuProfilerSwitch(int signal_number)
143 {
144   static unsigned profile_count;
145   static char base_profile_name[PATH_MAX];
146   static bool started = false;
147 
148   if (base_profile_name[0] == '\0') {
149     if (!GetUniquePathFromEnv("CPUPROFILE", base_profile_name)) {
150       RAW_LOG(FATAL,"Cpu profiler switch is registered but no CPUPROFILE is defined");
151       return;
152     }
153   }
154 
155   if (!started) {
156     char full_profile_name[PATH_MAX + 16];
157 
158     snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u",
159              base_profile_name, profile_count++);
160 
161     if(!ProfilerStart(full_profile_name)) {
162       RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
163               full_profile_name, strerror(errno));
164     }
165   } else {
166     ProfilerStop();
167   }
168   started = !started;
169 }
170 
171 // Profile data structure singleton: Constructor will check to see if
172 // profiling should be enabled.  Destructor will write profile data
173 // out to disk.
174 CpuProfiler CpuProfiler::instance_;
175 
176 // Initialize profiling: activated if getenv("CPUPROFILE") exists.
CpuProfiler()177 CpuProfiler::CpuProfiler()
178     : prof_handler_token_(NULL) {
179   // TODO(cgd) Move this code *out* of the CpuProfile constructor into a
180   // separate object responsible for initialization. With ProfileHandler there
181   // is no need to limit the number of profilers.
182   if (getenv("CPUPROFILE") == NULL) {
183     if (!FLAGS_cpu_profiler_unittest) {
184       RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n");
185     }
186     return;
187   }
188 
189   // We don't enable profiling if setuid -- it's a security risk
190 #ifdef HAVE_GETEUID
191   if (getuid() != geteuid()) {
192     if (!FLAGS_cpu_profiler_unittest) {
193       RAW_LOG(WARNING, "Cannot perform CPU profiling when running with setuid\n");
194     }
195     return;
196   }
197 #endif
198 
199   char *signal_number_str = getenv("CPUPROFILESIGNAL");
200   if (signal_number_str != NULL) {
201     long int signal_number = strtol(signal_number_str, NULL, 10);
202     if (signal_number >= 1 && signal_number <= 64) {
203       intptr_t old_signal_handler = reinterpret_cast<intptr_t>(signal(signal_number, CpuProfilerSwitch));
204       if (old_signal_handler == 0) {
205         RAW_LOG(INFO,"Using signal %d as cpu profiling switch", signal_number);
206       } else {
207         RAW_LOG(FATAL, "Signal %d already in use\n", signal_number);
208       }
209     } else {
210       RAW_LOG(FATAL, "Signal number %s is invalid\n", signal_number_str);
211     }
212   } else {
213     char fname[PATH_MAX];
214     if (!GetUniquePathFromEnv("CPUPROFILE", fname)) {
215       if (!FLAGS_cpu_profiler_unittest) {
216         RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n");
217       }
218       return;
219 	}
220 
221     if (!Start(fname, NULL)) {
222       RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
223               fname, strerror(errno));
224     }
225   }
226 }
227 
Start(const char * fname,const ProfilerOptions * options)228 bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) {
229   SpinLockHolder cl(&lock_);
230 
231   if (collector_.enabled()) {
232     return false;
233   }
234 
235   ProfileHandlerState prof_handler_state;
236   ProfileHandlerGetState(&prof_handler_state);
237 
238   ProfileData::Options collector_options;
239   collector_options.set_frequency(prof_handler_state.frequency);
240   if (!collector_.Start(fname, collector_options)) {
241     return false;
242   }
243 
244   filter_ = NULL;
245   if (options != NULL && options->filter_in_thread != NULL) {
246     filter_ = options->filter_in_thread;
247     filter_arg_ = options->filter_in_thread_arg;
248   }
249 
250   // Setup handler for SIGPROF interrupts
251   EnableHandler();
252 
253   return true;
254 }
255 
~CpuProfiler()256 CpuProfiler::~CpuProfiler() {
257   Stop();
258 }
259 
260 // Stop profiling and write out any collected profile data
Stop()261 void CpuProfiler::Stop() {
262   SpinLockHolder cl(&lock_);
263 
264   if (!collector_.enabled()) {
265     return;
266   }
267 
268   // Unregister prof_handler to stop receiving SIGPROF interrupts before
269   // stopping the collector.
270   DisableHandler();
271 
272   // DisableHandler waits for the currently running callback to complete and
273   // guarantees no future invocations. It is safe to stop the collector.
274   collector_.Stop();
275 }
276 
FlushTable()277 void CpuProfiler::FlushTable() {
278   SpinLockHolder cl(&lock_);
279 
280   if (!collector_.enabled()) {
281     return;
282   }
283 
284   // Unregister prof_handler to stop receiving SIGPROF interrupts before
285   // flushing the profile data.
286   DisableHandler();
287 
288   // DisableHandler waits for the currently running callback to complete and
289   // guarantees no future invocations. It is safe to flush the profile data.
290   collector_.FlushTable();
291 
292   EnableHandler();
293 }
294 
Enabled()295 bool CpuProfiler::Enabled() {
296   SpinLockHolder cl(&lock_);
297   return collector_.enabled();
298 }
299 
GetCurrentState(ProfilerState * state)300 void CpuProfiler::GetCurrentState(ProfilerState* state) {
301   ProfileData::State collector_state;
302   {
303     SpinLockHolder cl(&lock_);
304     collector_.GetCurrentState(&collector_state);
305   }
306 
307   state->enabled = collector_state.enabled;
308   state->start_time = static_cast<time_t>(collector_state.start_time);
309   state->samples_gathered = collector_state.samples_gathered;
310   int buf_size = sizeof(state->profile_name);
311   strncpy(state->profile_name, collector_state.profile_name, buf_size);
312   state->profile_name[buf_size-1] = '\0';
313 }
314 
EnableHandler()315 void CpuProfiler::EnableHandler() {
316   RAW_CHECK(prof_handler_token_ == NULL, "SIGPROF handler already registered");
317   prof_handler_token_ = ProfileHandlerRegisterCallback(prof_handler, this);
318   RAW_CHECK(prof_handler_token_ != NULL, "Failed to set up SIGPROF handler");
319 }
320 
DisableHandler()321 void CpuProfiler::DisableHandler() {
322   RAW_CHECK(prof_handler_token_ != NULL, "SIGPROF handler is not registered");
323   ProfileHandlerUnregisterCallback(prof_handler_token_);
324   prof_handler_token_ = NULL;
325 }
326 
327 // Signal handler that records the pc in the profile-data structure. We do no
328 // synchronization here.  profile-handler.cc guarantees that at most one
329 // instance of prof_handler() will run at a time. All other routines that
330 // access the data touched by prof_handler() disable this signal handler before
331 // accessing the data and therefore cannot execute concurrently with
332 // prof_handler().
prof_handler(int sig,siginfo_t *,void * signal_ucontext,void * cpu_profiler)333 void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext,
334                                void* cpu_profiler) {
335   CpuProfiler* instance = static_cast<CpuProfiler*>(cpu_profiler);
336 
337   if (instance->filter_ == NULL ||
338       (*instance->filter_)(instance->filter_arg_)) {
339     void* stack[ProfileData::kMaxStackDepth];
340 
341     // Under frame-pointer-based unwinding at least on x86, the
342     // top-most active routine doesn't show up as a normal frame, but
343     // as the "pc" value in the signal handler context.
344     stack[0] = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
345 
346     // We skip the top three stack trace entries (this function,
347     // SignalHandler::SignalHandler and one signal handler frame)
348     // since they are artifacts of profiling and should not be
349     // measured.  Other profiling related frames may be removed by
350     // "pprof" at analysis time.  Instead of skipping the top frames,
351     // we could skip nothing, but that would increase the profile size
352     // unnecessarily.
353     int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1,
354                                          3, signal_ucontext);
355 
356     void **used_stack;
357     if (depth > 0 && stack[1] == stack[0]) {
358       // in case of non-frame-pointer-based unwinding we will get
359       // duplicate of PC in stack[1], which we don't want
360       used_stack = stack + 1;
361     } else {
362       used_stack = stack;
363       depth++;  // To account for pc value in stack[0];
364     }
365 
366     instance->collector_.Add(depth, used_stack);
367   }
368 }
369 
370 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
371 
ProfilerRegisterThread()372 extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() {
373   ProfileHandlerRegisterThread();
374 }
375 
ProfilerFlush()376 extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() {
377   CpuProfiler::instance_.FlushTable();
378 }
379 
ProfilingIsEnabledForAllThreads()380 extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() {
381   return CpuProfiler::instance_.Enabled();
382 }
383 
ProfilerStart(const char * fname)384 extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) {
385   return CpuProfiler::instance_.Start(fname, NULL);
386 }
387 
ProfilerStartWithOptions(const char * fname,const ProfilerOptions * options)388 extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(
389     const char *fname, const ProfilerOptions *options) {
390   return CpuProfiler::instance_.Start(fname, options);
391 }
392 
ProfilerStop()393 extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() {
394   CpuProfiler::instance_.Stop();
395 }
396 
ProfilerGetCurrentState(ProfilerState * state)397 extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(
398     ProfilerState* state) {
399   CpuProfiler::instance_.GetCurrentState(state);
400 }
401 
ProfilerGetStackTrace(void ** result,int max_depth,int skip_count,const void * uc)402 extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace(
403     void** result, int max_depth, int skip_count, const void *uc) {
404   return GetStackTraceWithContext(result, max_depth, skip_count, uc);
405 }
406 
407 #else  // OS_CYGWIN
408 
409 // ITIMER_PROF doesn't work under cygwin.  ITIMER_REAL is available, but doesn't
410 // work as well for profiling, and also interferes with alarm().  Because of
411 // these issues, unless a specific need is identified, profiler support is
412 // disabled under Cygwin.
ProfilerRegisterThread()413 extern "C" void ProfilerRegisterThread() { }
ProfilerFlush()414 extern "C" void ProfilerFlush() { }
ProfilingIsEnabledForAllThreads()415 extern "C" int ProfilingIsEnabledForAllThreads() { return 0; }
ProfilerStart(const char * fname)416 extern "C" int ProfilerStart(const char* fname) { return 0; }
ProfilerStartWithOptions(const char * fname,const ProfilerOptions * options)417 extern "C" int ProfilerStartWithOptions(const char *fname,
418                                         const ProfilerOptions *options) {
419   return 0;
420 }
ProfilerStop()421 extern "C" void ProfilerStop() { }
ProfilerGetCurrentState(ProfilerState * state)422 extern "C" void ProfilerGetCurrentState(ProfilerState* state) {
423   memset(state, 0, sizeof(*state));
424 }
ProfilerGetStackTrace(void ** result,int max_depth,int skip_count,const void * uc)425 extern "C" int ProfilerGetStackTrace(
426     void** result, int max_depth, int skip_count, const void *uc) {
427   return 0;
428 }
429 
430 #endif  // OS_CYGWIN
431 
432 // DEPRECATED routines
ProfilerEnable()433 extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { }
ProfilerDisable()434 extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { }
435