Fix segfault by checking observer_class_lookup for NULL in observer callback #102
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Resolves open-telemetry/opentelemetry-php#1168 and most likely also open-telemetry/opentelemetry-php#1167
I have managed to reproduce the crash in open-telemetry/opentelemetry-php#1168 locally on PHP 8.2.10 with a minimal sample (running via Apache).
This happens because if nothing has been written to output,
php_output_deactivate
causessapi_send_headers
to be called, which in turn runs the header callback. Since header callback is a PHP function, the observer callback is invoked for that. The problem is thatphp_output_deactivate
was called byphp_request_shutdown
immediately after module RSHUTDOWN callbacks were called, in whichobserver_class_lookup
used by our observer callback is freed and set toNULL
.I have confirmed that the crash in the above sample stops reproducing after this change.
Additionally, the issue in open-telemetry/opentelemetry-php#1167 seems to be caused by another extension invoking PHP code in their RINIT. Since it is possible that the other extension is earlier in the load list, thus
observer_class_lookup
is not constructed yet (it is guaranteed to not be garbage because GINIT sets it toNULL
, so checking forNULL
should be safe) as that is done in RINIT. This new check should fix that as well.