Skip to content

Add xdebug integration with slow query breakpoint detection#21

Open
39ff wants to merge 2 commits into
mainfrom
claude/xdebug-integration-1xZ0G
Open

Add xdebug integration with slow query breakpoint detection#21
39ff wants to merge 2 commits into
mainfrom
claude/xdebug-integration-1xZ0G

Conversation

@39ff

@39ff 39ff commented Feb 23, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds xdebug integration to the MariaDB Query Profiler, enabling automatic debugger breakpoints when queries exceed a configurable duration threshold. This allows developers to interactively inspect slow queries in their IDE debugger.

Key Changes

  • New xdebug integration module (profiler_xdebug.c and profiler_xdebug.h):

    • Detects xdebug presence and step-debug mode availability
    • Supports both xdebug 2.x and 3.x with proper mode detection
    • Caches detection result per-request for performance
    • Provides xdebug_break() invocation via PHP function table
    • Compatible with PHP 5.3 through 8.4+
  • Query duration measurement:

    • Added microsecond-precision timing (profiler_get_microtime()) to all query execution paths
    • Measures duration for query(), send_query(), prepare(), and execute() methods
    • Passes duration to logging functions for recording
  • Slow query detection:

    • New profiler_check_slow_query() function checks if query duration exceeds threshold
    • Triggers xdebug_break() when threshold is exceeded and debugger is active
    • Integrated into all query execution paths
  • Configuration:

    • New INI setting: mariadb_profiler.xdebug_break_threshold (in seconds, default 0 = disabled)
    • Displayed in phpinfo output
  • Logging enhancements:

    • Updated all logging functions to accept and record duration_ms parameter
    • Duration displayed in raw logs as [%.3fms] format
    • Duration recorded in JSONL output as duration_ms field
    • Backward compatible with negative duration values (unmeasured queries)
  • Build system updates:

    • Updated config.m4 and config.w32 to include new source files

Implementation Details

  • Per-request xdebug detection caching avoids repeated module registry lookups
  • xdebug 3.x mode detection checks for "debug" in xdebug.mode setting
  • Fallback to xdebug_break function existence check for edge cases
  • Request shutdown hook resets detection cache for clean per-request state
  • All timing code uses gettimeofday() for cross-platform compatibility

https://claude.ai/code/session_01Ku8336fyCEdnwAVszkVmFS

Summary by CodeRabbit

  • 新機能
    • XDebugデバッガー統合を追加。スロークエリが閾値を超えると自動でブレークポイントを試行できます。
    • すべてのクエリ実行でミリ秒精度の実行時間を計測・ログ記録するようになりました。
    • 新しい設定項目 mariadb_profiler.xdebug_break_threshold を追加し、閾値を管理可能に。管理画面で閾値が表示されます。

Adds two key features to the MariaDB profiler:

1. Query execution time measurement: All mysqlnd hooks (query,
   send_query, prepare, execute) now measure wall-clock duration
   using gettimeofday. Duration is recorded in both JSONL logs
   (as "duration_ms" field) and raw logs (as [X.XXXms] column).

2. xdebug slow query breakpoint: When xdebug is loaded with
   step-debug mode active, queries exceeding the configured
   threshold automatically trigger xdebug_break(), pausing the
   debugger at the exact point of a slow query for interactive
   inspection.

New INI setting:
  mariadb_profiler.xdebug_break_threshold = 0
    Threshold in seconds (e.g. 0.5). Set to 0 to disable.
    PHP_INI_ALL so it can be changed per-request via ini_set().

New files:
  profiler_xdebug.c - xdebug detection (module registry + mode
    check) with per-request caching, and xdebug_break() caller
  profiler_xdebug.h - public API declarations

Compatible with PHP 5.3-8.4+ and xdebug 2.x/3.x.

https://claude.ai/code/session_01Ku8336fyCEdnwAVszkVmFS
@coderabbitai

coderabbitai Bot commented Feb 23, 2026

Copy link
Copy Markdown

Walkthrough

MariaDBプロファイラーにXDebug統合とクエリ実行時間計測を追加。ビルド設定に新ソースを追加し、閾値付きのXDebugブレーク呼び出し、ログへのduration_ms伝搬、リクエスト単位のXDebug検出/リセットを導入します。

Changes

Cohort / File(s) Summary
Build Configuration
ext/mariadb_profiler/config.m4, ext/mariadb_profiler/config.w32
拡張ビルドに profiler_xdebug.c を追加。Unix/Windows両環境でコンパイル対象を拡張。
XDebug 統合モジュール
ext/mariadb_profiler/profiler_xdebug.h, ext/mariadb_profiler/profiler_xdebug.c
新規モジュール:リクエスト単位のXDebug検出、デバッガ有効判定、xdebug_break呼び出し、検出キャッシュのリセットを実装(PHP5/7互換処理含む)。
モジュール設定 / ヘッダ
ext/mariadb_profiler/mariadb_profiler.c, ext/mariadb_profiler/php_mariadb_profiler.h
INI mariadb_profiler.xdebug_break_threshold(double, 秒)を追加しモジュールグローバルに格納。RSHUTDOWNでのxdebug検出リセット呼び出しを追加。ログAPIのシグネチャをduration_ms対応へ拡張。
タイミング計測とログ伝搬
ext/mariadb_profiler/profiler_log.c, ext/mariadb_profiler/profiler_mysqlnd_plugin.c
クエリ実行時間をマイクロ秒精度で計測してduration_msを生成。すべてのログ経路にduration_msを伝搬し、JSONL/RAW出力へ含める。閾値超過時はXDebugブレークの判定を行うロジックを追加。

Sequence Diagram(s)

sequenceDiagram
    participant PHP as PHP Engine
    participant Profiler as Profiler\n(mysqlnd_plugin)
    participant Logger as Logging System
    participant XDebug as XDebug Extension

    PHP->>Profiler: Execute query
    Profiler->>Profiler: Measure start (microtime)
    Profiler->>PHP: Forward query to DB / mysqlnd
    PHP-->>Profiler: Query result
    Profiler->>Profiler: Measure end, compute duration_ms
    Profiler->>XDebug: Check profiler_xdebug_is_debugger_active()
    XDebug-->>Profiler: active / inactive
    Profiler->>Profiler: Compare duration_ms to xdebug_break_threshold
    alt threshold exceeded & debugger active
        Profiler->>XDebug: profiler_xdebug_break()
        XDebug->>PHP: Break execution
    end
    Profiler->>Logger: Log query with duration_ms
    PHP->>Profiler: Request shutdown
    Profiler->>XDebug: profiler_xdebug_request_shutdown()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
くるっと跳ねてコードを見るよ、
時はマイクロ秒、音もなく。
閾値越えてぴたり止まれば、
うさぎは歌う、デバッグ万歳!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title "Add xdebug integration with slow query breakpoint detection" directly and accurately summarizes the main changes in the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 95.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/xdebug-integration-1xZ0G

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 509c25971a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ext/mariadb_profiler/profiler_xdebug.c Outdated
Comment on lines +49 to +52
mode_val = zend_ini_str("xdebug.mode", sizeof("xdebug.mode") - 1, 0);
if (mode_val && Z_TYPE_P(mode_val) == IS_STRING) {
/* xdebug 3.x: check for "debug" in the mode string */
if (strstr(Z_STRVAL_P(mode_val), "debug") != NULL) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use zend_string API when reading xdebug.mode

In PHP 8.3+ zend_ini_str() returns a zend_string*, but this code stores it as zval* and then applies Z_TYPE_P/Z_STRVAL_P, which reads the wrong memory layout. When xdebug.mode is present, this can mis-detect debug mode and may dereference invalid data while checking for "debug", causing unstable behavior in requests that execute slow-query checks.

Useful? React with 👍 / 👎.

Comment on lines 220 to 224
} else if (result != PASS && profiler_job_is_any_active()) {
/* Failed prepare has no subsequent execute(); log immediately with err status */
profiler_log_query(query, query_len, "err");
profiler_log_query(query, query_len, "err", duration_ms);
profiler_check_slow_query(duration_ms);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Run slow-query check for successful prepare on PHP 7+

In the PHP 7+ profiler_stmt::prepare() path, profiler_check_slow_query(duration_ms) is only called inside the result != PASS branch, so a successful but slow prepare() never triggers the configured xdebug breakpoint even though duration is measured. This drops slow-prepare detection on modern PHP versions and is inconsistent with the PHP 5 branch, which performs the check unconditionally.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
ext/mariadb_profiler/profiler_xdebug.c (1)

107-107: 未使用変数 retval_ptr

retval_ptr は宣言されていますが、一度も使用されていません。パイプライン警告こそ出ていませんが、コードの清潔さのために削除してください。

♻️ 修正案
 `#else`
-    zval *retval_ptr = NULL;
     zval *fname;
     zval retval;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ext/mariadb_profiler/profiler_xdebug.c` at line 107, Remove the unused local
variable retval_ptr from profiler_xdebug.c: locate the declaration "zval
*retval_ptr = NULL;" (symbol retval_ptr) and delete it; ensure there are no
remaining references to retval_ptr in the surrounding function so the build and
behavior remain unchanged.
ext/mariadb_profiler/php_mariadb_profiler.h (1)

128-131: xdebug関数の宣言が profiler_xdebug.h と重複しています。

profiler_xdebug_is_debugger_activeprofiler_xdebug_breakprofiler_xdebug_request_shutdown の宣言は profiler_xdebug.h(Lines 19, 29, 35)にも存在します。シグネチャが乖離するメンテナンスリスクがあります。

このヘッダーから削除して #include "profiler_xdebug.h" に委譲するか、一箇所にまとめることを検討してください。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ext/mariadb_profiler/php_mariadb_profiler.h` around lines 128 - 131, The
three xdebug function declarations profiler_xdebug_is_debugger_active,
profiler_xdebug_break, and profiler_xdebug_request_shutdown are duplicated here
and in profiler_xdebug.h; remove these declarations from php_mariadb_profiler.h
and delegate to the single authoritative header by adding `#include`
"profiler_xdebug.h" (or alternatively move the declarations into
php_mariadb_profiler.h and update profiler_xdebug.h to include it) so the
symbols are declared in one place to avoid signature drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ext/mariadb_profiler/profiler_log.c`:
- Around line 278-280: Add a nullable, serializable durationMs property to the
JetBrains plugin's QueryEntry data class so the JSONL "duration_ms" field is
preserved; specifically, in QueryEntry declare something like
`@SerialName`("duration_ms") val durationMs: Double? = null (or equivalent
nullable numeric type) so missing fields deserialize safely and present values
are captured.

In `@ext/mariadb_profiler/profiler_mysqlnd_plugin.c`:
- Around line 19-30: profiler_get_microtime currently calls gettimeofday
unconditionally which breaks Windows builds; add a Windows-compatible
implementation (or a compatibility shim) and use it from profiler_get_microtime,
profiler_log_get_timestamp, and profiler_log_get_microtime. Create a small
cross-platform utility (e.g., profiler_time.h/.c) that defines a portable
function (e.g., profiler_gettimeofday or profiler_get_microtime_impl) which uses
gettimeofday on POSIX and QueryPerformanceCounter/QueryPerformanceFrequency or
Windows equivalents on PHP_WIN32, update profiler_mysqlnd_plugin.c,
profiler_log.c to include and call that portable function, and guard includes
with `#ifdef` PHP_WIN32 so builds succeed on both platforms.

In `@ext/mariadb_profiler/profiler_xdebug.c`:
- Line 24: The global static variable xdebug_detected causes data races in ZTS
builds; move it into the module globals (PROFILER_G) so each thread has its own
copy: add an int xdebug_detected (0=unchecked,1=active,-1=inactive) to the
global struct in php_mariadb_profiler.h, replace references to the file-scope
xdebug_detected in profiler_xdebug_is_debugger_active() and
profiler_xdebug_request_shutdown() (and any other uses) to use
PROFILER_G->xdebug_detected (or the appropriate macro accessor), and remove the
static declaration from profiler_xdebug.c to avoid cross-thread sharing.
- Around line 30-77: The code in profiler_xdebug_detect incorrectly treats
zend_ini_str() as returning a zval*; replace that usage with zend_ini_string()
which returns a char* on PHP 7+, change the local variable mode_val from zval *
to char *mode_val, check for NULL and use strstr(mode_val, "debug") for the
"debug" check, and ensure you release the returned string (efree/ appropriate
API) after use; keep the existing fallback that checks for xdebug_break via
zend_string and EG(function_table) in the same function.

---

Nitpick comments:
In `@ext/mariadb_profiler/php_mariadb_profiler.h`:
- Around line 128-131: The three xdebug function declarations
profiler_xdebug_is_debugger_active, profiler_xdebug_break, and
profiler_xdebug_request_shutdown are duplicated here and in profiler_xdebug.h;
remove these declarations from php_mariadb_profiler.h and delegate to the single
authoritative header by adding `#include` "profiler_xdebug.h" (or alternatively
move the declarations into php_mariadb_profiler.h and update profiler_xdebug.h
to include it) so the symbols are declared in one place to avoid signature
drift.

In `@ext/mariadb_profiler/profiler_xdebug.c`:
- Line 107: Remove the unused local variable retval_ptr from profiler_xdebug.c:
locate the declaration "zval *retval_ptr = NULL;" (symbol retval_ptr) and delete
it; ensure there are no remaining references to retval_ptr in the surrounding
function so the build and behavior remain unchanged.

Comment on lines +278 to +280
if (duration_ms >= 0) {
fprintf(fp, ",\"duration_ms\":%.3f", duration_ms);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for QueryEntry.kt and check if it contains duration_ms or durationMs
fd "QueryEntry.kt" -x grep -n "duration" {} \; || echo "File not found or no duration references"

Repository: 39ff/php-ext-mariadb-salvage

Length of output: 112


🏁 Script executed:

#!/bin/bash
# Also check the directory structure to understand the layout
find . -name "*.kt" -type f | head -20

Repository: 39ff/php-ext-mariadb-salvage

Length of output: 1837


🏁 Script executed:

#!/bin/bash
# Check the profiler_log.c file around lines 278-280
if [ -f "ext/mariadb_profiler/profiler_log.c" ]; then
    sed -n '275,285p' ext/mariadb_profiler/profiler_log.c
else
    echo "File not found"
fi

Repository: 39ff/php-ext-mariadb-salvage

Length of output: 309


🏁 Script executed:

#!/bin/bash
# Read the QueryEntry.kt file to see its current structure
cat -n ./jetbrains-plugin/src/main/kotlin/com/mariadbprofiler/plugin/model/QueryEntry.kt

Repository: 39ff/php-ext-mariadb-salvage

Length of output: 9818


🏁 Script executed:

#!/bin/bash
# Check the git status or recent changes to see if QueryEntry.kt was supposed to be modified
git log --oneline -20

Repository: 39ff/php-ext-mariadb-salvage

Length of output: 143


🏁 Script executed:

#!/bin/bash
# Search for any recent mentions of durationMs or duration_ms in the codebase
rg "durationMs|duration_ms" --max-count=20

Repository: 39ff/php-ext-mariadb-salvage

Length of output: 4438


LGTM!

JSONL出力の duration_ms フィールドは計測済みの場合のみ出力され、%.3f フォーマットでミリ秒精度を保持しています。ただし、JetBrains プラグイン側の QueryEntry データクラスに durationMs フィールド(@SerialName("duration_ms") 付き)の追加がまだ必要です。このフィールドなしではJSON逆シリアル化時に値が失われます。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ext/mariadb_profiler/profiler_log.c` around lines 278 - 280, Add a nullable,
serializable durationMs property to the JetBrains plugin's QueryEntry data class
so the JSONL "duration_ms" field is preserved; specifically, in QueryEntry
declare something like `@SerialName`("duration_ms") val durationMs: Double? = null
(or equivalent nullable numeric type) so missing fields deserialize safely and
present values are captured.

Comment on lines +19 to +30
#ifndef PHP_WIN32
# include <sys/time.h>
#endif

/* {{{ profiler_get_microtime
* Get current time in seconds with microsecond precision. */
static double profiler_get_microtime(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Windowsビルドで gettimeofday() が未定義になります。

<sys/time.h> のインクルードは #ifndef PHP_WIN32 でガードされていますが、profiler_get_microtime()gettimeofday() を無条件に呼び出しています。Windows には gettimeofday() が存在しないため、Windowsビルドで警告/エラーが発生します(パイプラインの警告でも確認済み)。

Windows互換の実装を追加するか、互換レイヤーを使用してください。

🔧 Windows互換の実装案
 `#ifndef` PHP_WIN32
 # include <sys/time.h>
 `#endif`
 
+#ifdef PHP_WIN32
+# include <windows.h>
+static int profiler_win_gettimeofday(struct timeval *tv)
+{
+    FILETIME ft;
+    unsigned __int64 tmpres = 0;
+    GetSystemTimeAsFileTime(&ft);
+    tmpres |= ft.dwHighDateTime;
+    tmpres <<= 32;
+    tmpres |= ft.dwLowDateTime;
+    /* FILETIME epoch is 1601-01-01; convert to Unix epoch */
+    tmpres -= 116444736000000000ULL;
+    tmpres /= 10; /* to microseconds */
+    tv->tv_sec = (long)(tmpres / 1000000UL);
+    tv->tv_usec = (long)(tmpres % 1000000UL);
+    return 0;
+}
+# define gettimeofday(tv, tz) profiler_win_gettimeofday(tv)
+#endif
+
 /* {{{ profiler_get_microtime

なお、同じ問題は profiler_log.cprofiler_log_get_timestamp()profiler_log_get_microtime() にも存在します。共通のユーティリティヘッダーに gettimeofday の互換実装をまとめることを推奨します。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ext/mariadb_profiler/profiler_mysqlnd_plugin.c` around lines 19 - 30,
profiler_get_microtime currently calls gettimeofday unconditionally which breaks
Windows builds; add a Windows-compatible implementation (or a compatibility
shim) and use it from profiler_get_microtime, profiler_log_get_timestamp, and
profiler_log_get_microtime. Create a small cross-platform utility (e.g.,
profiler_time.h/.c) that defines a portable function (e.g.,
profiler_gettimeofday or profiler_get_microtime_impl) which uses gettimeofday on
POSIX and QueryPerformanceCounter/QueryPerformanceFrequency or Windows
equivalents on PHP_WIN32, update profiler_mysqlnd_plugin.c, profiler_log.c to
include and call that portable function, and guard includes with `#ifdef`
PHP_WIN32 so builds succeed on both platforms.

* 1 = xdebug step-debug is available
* -1 = xdebug not available / no step-debug
*/
static int xdebug_detected = 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

xdebug_detected はZTS(スレッドセーフ)ビルドでデータ競合が発生します。

static int xdebug_detected はファイルスコープのグローバル変数であり、ZTSビルドでは全スレッドで共有されます。複数のリクエストが並行して処理される場合、profiler_xdebug_is_debugger_active() での読み書きと profiler_xdebug_request_shutdown() でのリセットが競合し、不正な値を読み取る可能性があります。

モジュールグローバル(PROFILER_G)に移動させるべきです。

🔧 修正案: モジュールグローバルに移動

php_mariadb_profiler.h のグローバル構造体に追加:

int xdebug_detected; /* 0=unchecked, 1=active, -1=inactive */

profiler_xdebug.c での変更:

-static int xdebug_detected = 0;
-
 /* ... */

 int profiler_xdebug_is_debugger_active(void)
 {
+    TSRMLS_FETCH();
-    if (xdebug_detected == 0) {
-        xdebug_detected = profiler_xdebug_detect() ? 1 : -1;
+    if (PROFILER_G(xdebug_detected) == 0) {
+        PROFILER_G(xdebug_detected) = profiler_xdebug_detect() ? 1 : -1;
     }
-    return (xdebug_detected == 1);
+    return (PROFILER_G(xdebug_detected) == 1);
 }

 void profiler_xdebug_request_shutdown(void)
 {
-    xdebug_detected = 0;
+    TSRMLS_FETCH();
+    PROFILER_G(xdebug_detected) = 0;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ext/mariadb_profiler/profiler_xdebug.c` at line 24, The global static
variable xdebug_detected causes data races in ZTS builds; move it into the
module globals (PROFILER_G) so each thread has its own copy: add an int
xdebug_detected (0=unchecked,1=active,-1=inactive) to the global struct in
php_mariadb_profiler.h, replace references to the file-scope xdebug_detected in
profiler_xdebug_is_debugger_active() and profiler_xdebug_request_shutdown() (and
any other uses) to use PROFILER_G->xdebug_detected (or the appropriate macro
accessor), and remove the static declaration from profiler_xdebug.c to avoid
cross-thread sharing.

Comment thread ext/mariadb_profiler/profiler_xdebug.c
zend_ini_str() does not exist in any PHP version. The correct API
is zend_ini_string() which returns char* (NULL if setting absent).
Also removes an unused variable in the PHP 5.x code path.

https://claude.ai/code/session_01Ku8336fyCEdnwAVszkVmFS

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1fa4ce8a7c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +54 to +55
if (strstr(mode_str, "debug") != NULL) {
return 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify debugger session before treating debug mode as active

This branch returns active as soon as xdebug.mode contains debug, but that only means step-debug functionality is enabled, not that an IDE session is connected. In environments with xdebug.mode=debug and no attached client (for example start_with_request=trigger with no trigger), slow queries will still call xdebug_break(), which repeatedly attempts to connect and emits "Could not connect to debugging client" warnings, adding avoidable latency and log noise.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
ext/mariadb_profiler/profiler_xdebug.c (2)

103-103: PHP 7.1 以降、call_user_functionfunction_table 引数は使用されず、NULL を渡すべきです

PHP 7.1.0 以降、call_user_functionfunction_table 引数は使用されず、常に NULL を渡すべきとされています。EG(function_table) を渡してもエラーにはなりませんが、PHP 7.1+ では無視されます。なお、このブランチは PHP_VERSION_ID >= 70000 で囲まれており、PHP 7.0 では引数が使用されていた可能性があるため、厳密には 7.1 以降でのみ適用される点に注意してください。

♻️ 変更案
-    if (call_user_function(EG(function_table), NULL, &fname, &retval, 0, NULL) == SUCCESS) {
+    if (call_user_function(NULL, NULL, &fname, &retval, 0, NULL) == SUCCESS) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ext/mariadb_profiler/profiler_xdebug.c` at line 103, The call to
call_user_function currently passes EG(function_table) but per PHP 7.1+ the
function_table argument must be NULL; update the invocation in profiler_xdebug.c
to pass NULL instead of EG(function_table) and adjust the surrounding
preprocessor guards so this change applies only for PHP_VERSION_ID >= 70100
(keep the original behavior for older PHP versions where function_table was
used); the symbol to update is the call_user_function(...) call that currently
uses EG(function_table).

103-103: PHP 8.0 以降では call_user_function の第1引数 function_table は無視されます

PHP 8.0+では、call_user_function()function_table パラメータは使用されず、NULL を渡すことが推奨されます。一方、PHP 7.x では NULL を渡すと既定のグローバル関数テーブルへのフォールバックが発生します。

このコードは PHP 5.x と PHP 7+ の両方に対応しているため、NULL は両方のバージョンで動作し、PHP 8.0+ ではより明確で将来互換性の高い記述となります。

♻️ 変更案
-    if (call_user_function(EG(function_table), NULL, &fname, &retval, 0, NULL) == SUCCESS) {
+    if (call_user_function(NULL, NULL, &fname, &retval, 0, NULL) == SUCCESS) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ext/mariadb_profiler/profiler_xdebug.c` at line 103, The call to
call_user_function currently passes EG(function_table) which is ignored on PHP
8+; update the invocation to pass NULL instead so it works correctly on PHP 8+
while still falling back on PHP 7.x/5.x behavior—locate the call_user_function
usage that passes EG(function_table) (the call referencing fname and retval) and
replace the first argument with NULL.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@ext/mariadb_profiler/profiler_xdebug.c`:
- Around line 126-130: profiler_xdebug_request_shutdown currently resets the
global xdebug_detected directly which causes ZTS data races; replace the direct
write with the thread-safe PHP extension globals accessor by setting
PROFILER_G(xdebug_detected) = 0 inside profiler_xdebug_request_shutdown (and
remove/replace any other direct uses of the xdebug_detected global), ensuring
you include the proper header/externs so PROFILER_G is available and maintain
consistent use of PROFILER_G(xdebug_detected) across functions that read or
write this flag.
- Line 24: グローバルな static int xdebug_detected は
ZTS(マルチスレッド)ビルドでスレッド間共有されデータ競合を起こすため、スレッドローカル化して競合を防いでください: ファイル内の宣言を static int
xdebug_detected = 0; から ZEND_TLS int xdebug_detected = 0;
のようにスレッドローカルストレージに置き換え(またはプロジェクトで使っている PHP/TSSM の TLS
マクロに合わせて適切なマクロを使用)し、profiler_xdebug_is_debugger_active() と
profiler_xdebug_request_shutdown() は既存の参照をそのまま使って TLS 変数を読み書きするようにしてください(もし TLS
が使えない環境があるなら代替として mutex/スピンロックでアクセスを保護してください)。

---

Nitpick comments:
In `@ext/mariadb_profiler/profiler_xdebug.c`:
- Line 103: The call to call_user_function currently passes EG(function_table)
but per PHP 7.1+ the function_table argument must be NULL; update the invocation
in profiler_xdebug.c to pass NULL instead of EG(function_table) and adjust the
surrounding preprocessor guards so this change applies only for PHP_VERSION_ID
>= 70100 (keep the original behavior for older PHP versions where function_table
was used); the symbol to update is the call_user_function(...) call that
currently uses EG(function_table).
- Line 103: The call to call_user_function currently passes EG(function_table)
which is ignored on PHP 8+; update the invocation to pass NULL instead so it
works correctly on PHP 8+ while still falling back on PHP 7.x/5.x
behavior—locate the call_user_function usage that passes EG(function_table) (the
call referencing fname and retval) and replace the first argument with NULL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants