Add support for XEvent logging and bump API version to v3 - #90
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a v3 extension interface update to support optional host callbacks, enabling extensions (specifically the .NET C# extension) to log XEvents back through the host infrastructure.
Changes:
- Bumped
EXTERNAL_LANGUAGE_EXTENSION_APIfrom 2 to 3 and added a new optionalSetHostCallbacksAPI + callback struct/type in the shared native interface header. - Implemented native
SetHostCallbacksin the .NET C# extension and forwarded the callback struct to the managed layer. - Added managed callback delegates/structs plus a
Logging.LogXEvent(...)helper that invokes the host-provided callback.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| extension-host/include/sqlexternallanguage.h | Bumps API version to v3; adds host callback typedef/struct and SetHostCallbacks API declaration. |
| language-extensions/dotnet-core-CSharp/include/nativecsharpextension.h | Declares SetHostCallbacks export and stores a host-callbacks pointer. |
| language-extensions/dotnet-core-CSharp/src/native/nativecsharpextension.cpp | Implements native SetHostCallbacks; resets host callbacks on cleanup. |
| language-extensions/dotnet-core-CSharp/src/managed/CSharpExtension.cs | Adds managed callback delegate/struct and implements managed SetHostCallbacks. |
| language-extensions/dotnet-core-CSharp/src/managed/utils/Logging.cs | Stores callback delegate and adds LogXEvent helper for managed code. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
SicongLiu2000
left a comment
There was a problem hiding this comment.
Review Summary — XEvent Logging Callback API (v3)
Nice feature — clean API surface and good test coverage. Three items I'd want addressed before merge, plus several medium-severity hardening suggestions:
Must-fix (High)
- TOCTOU on
_logXEventCallback(Logging.cs) — snapshot to local before null-check and invocation to prevent NRE from concurrentSetLogXEventCallback(null). - Use-after-free in
Cleanup()(nativecsharpextension.cpp) — must clear the managed-side callback delegate before tearing down the .NET runtime, otherwise background threads can invoke a stale host function pointer. char*vsbyte*delegate type mismatch (CSharpExtension.cs) — delegate declareschar*(2-byte UTF-16) but actually receivesbyte*(1-byte UTF-8). Should bebyte*to match the nativeSQLCHAR*.
Should-fix (Medium)
- Dangling pointer —
g_hostCallbacksstores borrowed pointer; copy the struct or remove the dead global. fixedon empty array — yields null pointer passed to native code; guard the empty-message case.staticglobals in header — pre-existing issue, but the newg_hostCallbacksfollows the pattern;extern+ single definition is correct.
Consider (Low)
- Version check could use a
MAX_SUPPORTEDconstant for future extensibility. ulongvsnuintforSQLULENif 32-bit is ever a target.
See inline comments for details and suggested fixes.
SicongLiu2000
left a comment
There was a problem hiding this comment.
All 8 findings addressed — TOCTOU snapshot, use-after-free ordering, type mismatch, dangling pointer copy, fixed-null guard, extern globals, version constant, and typo. Good test coverage with the new GTest suite. LGTM 👍
c3c4392 to
875619b
Compare
This reverts commit 7b6bdb3.
…nsion name otherwise
875619b to
2f9a8c9
Compare
MHN (monamaki)
left a comment
There was a problem hiding this comment.
Approving to deliver.
please ensure addressing comments and also we need to follow this model:
RE: Extension API v3 versioning — negotiate-down vs strict check — need your input
…ls + Cleanup teardown). Native .so was exporting/executing v3 code that aborts on the v2 host; managed decimal + v2 pin retained
…e + host-callback headers; API stays v2). Native .so now byte-identical to proven-working baseline; managed decimal retained
Reconcile the Linux support with main, which has since added DECIMAL (microsoft#83), ZIP archive InstallExternalLibrary (microsoft#85), and SetHostCallbacks/API v3 (microsoft#90). Conflict + fallout resolutions (Linux portability for the new main code): - CMakeLists.txt: keep the WIN32/else split (Linux gtest-from-source, -fshort-wchar, dl/pthread linking); drop main''s unconditional -D_WIN64/_WINDOWS which broke Linux. - CSharpExtensionApiTests.cpp GetHandles(): resolve the InstallExternalLibrary/ UninstallExternalLibrary symbol lookups for both the Windows (GetProcAddress) and Linux (dlsym) branches. - CSharpLibraryTests.cpp (new, microsoft#85): add cross-platform GetExecutablePath() helper (readlink on Linux), guard LocalFree/HLOCAL with free() on Linux. - CSharpSetHostCallbacksTests.cpp (new, microsoft#90): make RESOLVE_SET_HOST_CALLBACKS use dlsym on Linux. - run-...-test.sh: export ENL_ROOT so the test binary can locate test_packages.
This pull request introduces a new optional host callback API (version 3) for SQL language extensions, enabling extensions to log XEvents back to the host infrastructure. The update defines new callback types and structures in the native interface, implements the callback registration and invocation in both native and managed (.NET) layers, and provides the necessary glue to allow the managed extension to log messages through the host's event system.
The most important changes are:
API and Interface Additions:
EXTERNAL_LANGUAGE_EXTENSION_APIversion from 2 to 3 insqlexternallanguage.hto indicate the new optional host callback API.PFunc_ExtensionLogXEventcallback type, theSQLEXTENSION_HOST_CALLBACKSstructure, and theSetHostCallbacksAPI tosqlexternallanguage.h, allowing the host to provide callback functions to extensions.Native Extension Integration:
SetHostCallbacksfunction and theg_hostCallbackspointer tonativecsharpextension.hand implemented their logic innativecsharpextension.cpp, storing the host callbacks and forwarding them to the managed layer. [1] [2]Managed Extension Support:
CSharpExtension.cs, and implemented theSetHostCallbacksmethod to receive and store the callback, enabling managed code to log XEvents through the host.Loggingutility inLogging.csto store the host-provided callback and added theLogXEventmethod, allowing managed code to log messages through the host's XEvent infrastructure. [1] [2]Here's the compatibility matrix for general Extension API in terms of host callbacks.
SetHostCallbacksis not defined in Extension and host does not expect it and does not call it.SetHostCallbacksis not defined in Extension, but host does check it and skips calling it since it's not defined on Extension side.SetHostCallbacksis defined in Extension but host does not expect it and does not call it.SetHostCallbacksis defined on both sides and host calls it.Here's the compatibility matrix for Host Callbacks API. Here,
v2can be interpreted asvNext.v1is the current version present in this pull request.LogXEventcallback and Extension expects only that one, and saves its address.LogXEvent, but Extension reads onlyLogXEvent, ignoring other callbacks.LogXEventcallback, and Extension expects additional functions apart fromLogXEvent, but since they arenullptrin a struct, they will be skipped.LogXEvent, and Extension expects additional functions apart fromLogXEvent, saves their addresses and calls them.