Skip to content

Commit

Permalink
Set various PHP engine hooks only when the relevant feature is enabled (
Browse files Browse the repository at this point in the history
#1211)

* Set various PHP engine hooks only when the relevant feature is enabled

* Fix wrong option name in log message

* Fixed compilation error

* Fixed compilation error (part 2)
  • Loading branch information
SergeyKleyman committed Aug 20, 2024
1 parent 88fe3ea commit ed239db
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 22 deletions.
17 changes: 16 additions & 1 deletion agent/native/ext/Hooking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include <memory>
#include <string_view>

#include "log.h"

#define ELASTIC_APM_CURRENT_LOG_CATEGORY ELASTIC_APM_LOG_CATEGORY_EXT_INFRA

namespace elasticapm::php {

#if PHP_VERSION_ID < 80000
Expand Down Expand Up @@ -88,10 +92,21 @@ static void elastic_interrupt_function(zend_execute_data *execute_data) {
} zend_end_try();
}

void Hooking::replaceHooks() {
void Hooking::replaceHooks(bool cfgCaptureErrors, bool cfgInferredSpansEnabled) {
if (cfgInferredSpansEnabled) {
zend_execute_internal = elastic_execute_internal;
zend_interrupt_function = elastic_interrupt_function;
ELASTIC_APM_LOG_DEBUG( "Replaced zend_execute_internal and zend_interrupt_function hooks" );
} else {
ELASTIC_APM_LOG_DEBUG( "NOT replacing zend_execute_internal and zend_interrupt_function hooks because profiling_inferred_spans_enabled configuration option is set to false" );
}

if (cfgCaptureErrors) {
zend_error_cb = elastic_apm_error_cb;
ELASTIC_APM_LOG_DEBUG( "Replaced zend_error_cb hook" );
} else {
ELASTIC_APM_LOG_DEBUG( "NOT replacing zend_error_cb hook because capture_errors configuration option is set to false" );
}
}

}
2 changes: 1 addition & 1 deletion agent/native/ext/Hooking.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Hooking {
zend_error_cb = original_zend_error_cb_;
}

void replaceHooks();
void replaceHooks(bool cfgCaptureErrors, bool cfgInferredSpansEnabled);

zend_execute_internal_t getOriginalExecuteInternal() {
return original_execute_internal_;
Expand Down
41 changes: 21 additions & 20 deletions agent/native/ext/lifecycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ typedef void (* ZendThrowExceptionHook )(
);

// static bool elasticApmZendErrorCallbackSet = false;
static bool elasticApmZendThrowExceptionHookSet = false;
static bool elasticApmZendThrowExceptionHookReplaced = false;
static ZendThrowExceptionHook originalZendThrowExceptionHook = NULL;

void resetLastThrown() {
Expand Down Expand Up @@ -186,41 +186,42 @@ void elasticApmZendThrowExceptionHook(
#endif
)
{
Tracer* const tracer = getGlobalTracer();
const ConfigSnapshot* config = getTracerCurrentConfigSnapshot( tracer );
if (config->captureErrors) {
elasticApmZendThrowExceptionHookImpl( thrownObj );
}
elasticApmZendThrowExceptionHookImpl( thrownObj );

if (originalZendThrowExceptionHook == elasticApmZendThrowExceptionHook) {
ELASTIC_APM_LOG_CRITICAL( "originalZendThrowExceptionHook == elasticApmZendThrowExceptionHook" );
return;
}


if ( originalZendThrowExceptionHook != NULL )
{
originalZendThrowExceptionHook( thrownObj );
}
}


static void registerExceptionHooks() {
if (!elasticApmZendThrowExceptionHookSet) {
originalZendThrowExceptionHook = zend_throw_exception_hook;
zend_throw_exception_hook = elasticApmZendThrowExceptionHook;
elasticApmZendThrowExceptionHookSet = true;
ELASTIC_APM_LOG_DEBUG( "Set zend_throw_exception_hook: %p (%s elasticApmZendThrowExceptionHook) -> %p"
, originalZendThrowExceptionHook, originalZendThrowExceptionHook == elasticApmZendThrowExceptionHook ? "==" : "!="
, elasticApmZendThrowExceptionHook );
} else {
ELASTIC_APM_LOG_WARNING( "zend_erzend_throw_exception_hook already set: %p. Original: %p, Elastic: %p", zend_throw_exception_hook, originalZendThrowExceptionHook, elasticApmZendThrowExceptionHook );
static void registerExceptionHooks(const ConfigSnapshot& config) {
if (!config.captureErrors) {
ELASTIC_APM_LOG_DEBUG( "NOT replacing zend_throw_exception_hook hook because capture_errors configuration option is set to false" );
return;
}

if (elasticApmZendThrowExceptionHookReplaced) {
ELASTIC_APM_LOG_WARNING( "zend_throw_exception_hook already replaced: %p. Original: %p, Elastic: %p", zend_throw_exception_hook, originalZendThrowExceptionHook, elasticApmZendThrowExceptionHook );
return;
}

originalZendThrowExceptionHook = zend_throw_exception_hook;
zend_throw_exception_hook = elasticApmZendThrowExceptionHook;
elasticApmZendThrowExceptionHookReplaced = true;
ELASTIC_APM_LOG_DEBUG( "Replaced zend_throw_exception_hook: %p (%s elasticApmZendThrowExceptionHook) -> %p"
, originalZendThrowExceptionHook, originalZendThrowExceptionHook == elasticApmZendThrowExceptionHook ? "==" : "!="
, elasticApmZendThrowExceptionHook );
}


static void unregisterExceptionHooks() {
if (elasticApmZendThrowExceptionHookSet) {
if (elasticApmZendThrowExceptionHookReplaced) {
ZendThrowExceptionHook zendThrowExceptionHookBeforeRestore = zend_throw_exception_hook;
zend_throw_exception_hook = originalZendThrowExceptionHook;
ELASTIC_APM_LOG_DEBUG( "Restored zend_throw_exception_hook: %p (%s elasticApmZendThrowExceptionHook: %p) -> %p"
Expand Down Expand Up @@ -277,7 +278,7 @@ void elasticApmModuleInit( int moduleType, int moduleNumber )

registerCallbacksToLogFork();
registerAtExitLogging();
registerExceptionHooks();
registerExceptionHooks(*config);

curlCode = curl_global_init( CURL_GLOBAL_ALL );
if ( curlCode != CURLE_OK )
Expand All @@ -290,7 +291,7 @@ void elasticApmModuleInit( int moduleType, int moduleNumber )

astInstrumentationOnModuleInit( config );

elasticapm::php::Hooking::getInstance().replaceHooks();
elasticapm::php::Hooking::getInstance().replaceHooks(config->captureErrors, config->profilingInferredSpansEnabled);

if (php_check_open_basedir_ex(config->bootstrapPhpPartFile, false) != 0) {
ELASTIC_APM_LOG_WARNING(
Expand Down

0 comments on commit ed239db

Please sign in to comment.