Project Xenon - initial checkin
commit5ff703ef9279cc9e43d1cb852f35014890ad0486
authorEdward Kandrot <ekandrot@fb.com>
Sat, 12 Apr 2014 15:33:02 +0000 (12 08:33 -0700)
committerSara Golemon <sgolemon@fb.com>
Mon, 14 Apr 2014 16:06:10 +0000 (14 09:06 -0700)
treec7b4a7d954aabe4d471aeefc8d2801a6a46a1584
parentb1d9c531223a2c6cfeeee41deddea256874ca2fd
Project Xenon - initial checkin

There are two runtime options for Xenon:  ForceAlwaysOn and Period.
ForceAlwaysOn - defaults to false.  If true, then the Xenon will capture stacks at every function exit and enter.
Period - sets how often Xenon’s signal handler should fire.  Current thinking is once per machine per 10 minutes.

A php command:
xenon_get_data - gets the php and async stacks that were captured for this thread.

There are two objects:
Xenon - sets up and keeps track of the process signal handler
XenonThreadData - thread local storage for the gathered stack snapshots

There are five methods that are the interface to Xenon:
start - called to start the Xenon timer
stop - undoes all that start did, stopping threads, timers, etc.
onTimer - the call back from the signal handler for SIGVTALRM
surpriseAll - sets the Surprise flags for all threads
log - called to log the php and async stack, if needed

Order of operation:
Xenon::start is called from hhvm when the process is started.  If Xenon is enabled, this sets up a timer for the seconds based on the runtime options.
When the timer is fired, it sets a semaphre, which another thread is
waiting for.  The thread then wakes and Surprises all of the threads.  It does this via a routine within ThreadInfo that applies a function per thread, with a lambda that sets the Xenon Surprise flag.
Each thread continues its normal execution, but at function exit/enter it checks to see if Xenon Surprise flag has been set.
If it has, then it logs the async and php stack into reuqest-thread local storage.  If it happens multiple times before this thread ends, it accumulates the stacks.
When a request is ending, on the www side, a request is made for any stored data, which is formatted and returned.

When a request is started, any lingering Xenon Surprise flag that might have been set is cleared, to remove bias.
When a request ends, all Array data used for stack storage is invalid and can not be used after this point.
There are two methods within XenonThreadData to handle these cases.

Changes to existing code:
added a method to ThreadInfo that allows the application of a function per thread, if the lock can be acquired
added tests to function Enter/Exit in Event Hook
added a timer handler for Xenon, so changed the default signal handler callback to recognize Xenon vs its original timer handler

Reviewed By: @mikemag

Differential Revision: D1239666
20 files changed:
hphp/NEWS
hphp/compiler/parser/parser.cpp
hphp/runtime/base/program-functions.cpp
hphp/runtime/base/request-injection-data.cpp
hphp/runtime/base/request-injection-data.h
hphp/runtime/base/request-local.h
hphp/runtime/base/runtime-option.cpp
hphp/runtime/base/runtime-option.h
hphp/runtime/base/thread-info.cpp
hphp/runtime/base/thread-info.h
hphp/runtime/ext/ext_xenon.cpp [new file with mode: 0644]
hphp/runtime/ext/ext_xenon.h [new file with mode: 0644]
hphp/runtime/ext/ext_xenon.php [new file with mode: 0644]
hphp/runtime/vm/event-hook.cpp
hphp/test/quick/xenon/config.hdf [new file with mode: 0644]
hphp/test/quick/xenon/xenon.php [new file with mode: 0644]
hphp/test/quick/xenon/xenon.php.expectf [new file with mode: 0644]
hphp/test/quick/xenon/xenon_init.php [new file with mode: 0644]
hphp/test/quick/xenon/xenon_init.php.expectf [new file with mode: 0644]
hphp/util/trace.h