src/node_errors: add re-entrancy guard to TriggerUncaughtException - #64327
src/node_errors: add re-entrancy guard to TriggerUncaughtException#64327themuuln wants to merge 2 commits into
Conversation
d6df9be to
955d7e4
Compare
| @@ -191,6 +191,7 @@ static std::string GetErrorSource(Isolate* isolate, | |||
|
|
|||
| static std::atomic<bool> is_in_oom{false}; | |||
| static thread_local std::atomic<bool> is_retrieving_js_stacktrace{false}; | |||
| static thread_local bool is_in_uncaught_exception = false; | |||
There was a problem hiding this comment.
Does this need to be std::atomic<bool> like is_retrieving_js_stacktrace? If not, a short comment explaining why would be good.
There was a problem hiding this comment.
Fair enough β added a comment explaining why. Since this flag only guards re-entrancy on the current thread, thread_local handles the isolation and no atomic is needed.
|
@jasnell PTAL! Could you please re-review and re-approve? |
β¦in TriggerUncaughtException Add a thread_local re-entrancy guard to TriggerUncaughtException() that detects when the JS-level exception handler (process._fatalException) itself triggers another exception through the inspector protocol. This prevents the infinite loop: TriggerUncaughtException -> InspectorConsoleCall -> TriggerUncaughtException -> InspectorConsoleCall -> ... When re-entrancy is detected, the function prints a diagnostic with the formatted exception to stderr using FormatCaughtException (which avoids the inspector path entirely), then aborts the process. Fixes: nodejs#64326 Signed-off-by: Temuulen Undrakhbayar <[email protected]>
Signed-off-by: Temuulen Undrakhbayar <[email protected]>
b9c03ae to
7cd61df
Compare
|
@jasnell Thanks again for the review! Iβve added the missing DCO sign-offs. It looks like the GitHub Actions runs are waiting for maintainer approvalβwhen you have a chance, could you approve those and start Jenkins with the request-ci label? |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Add a thread_local re-entrancy guard to TriggerUncaughtException() that detects when the JS-level exception handler (process._fatalException) triggers another exception through the inspector protocol. This prevents the infinite loop: TriggerUncaughtException -> InspectorConsoleCall -> TriggerUncaughtException -> InspectorConsoleCall -> ... When re-entrancy is detected, the function prints a diagnostic with the formatted exception to stderr using FormatCaughtException (which avoids the inspector path entirely), then aborts the process. Fixes: #64326 Signed-off-by: Temuulen Undrakhbayar <[email protected]> PR-URL: #64327 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
|
Landed in 460b202 |
Add a thread_local re-entrancy guard to TriggerUncaughtException() that detects when the JS-level exception handler (process._fatalException) triggers another exception through the inspector protocol. This prevents the infinite loop: TriggerUncaughtException -> InspectorConsoleCall -> TriggerUncaughtException -> InspectorConsoleCall -> ... When re-entrancy is detected, the function prints a diagnostic with the formatted exception to stderr using FormatCaughtException (which avoids the inspector path entirely), then aborts the process. Fixes: #64326 Signed-off-by: Temuulen Undrakhbayar <[email protected]> PR-URL: #64327 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
Problem
When an uncaught exception triggers
TriggerUncaughtExceptionβ the JS handler (process._fatalException) βconsole.errorβ the inspector protocol (InspectorConsoleCall) throws again, V8 re-entersTriggerUncaughtException. This creates a tight infinite loop:Each iteration:
This was observed in production with napi-rs plugins calling
console.errorduring uncaught exception handling, but any JS handler that triggers inspector protocol activity duringprocess._fatalExceptioncan hit it.Fix
Add a
thread_localre-entrancy guard toTriggerUncaughtException(). If the function is re-entered while already processing an uncaught exception, it:FormatCaughtException(pure V8 string ops β no JS, no inspector)PrintToStderrAndFlushABORT()to terminate the processAn RAII scope guard resets the flag when
TriggerUncaughtExceptionreturns normally (e.g.,env->Exit()path).The guard lives entirely in
node_errors.ccβ no header changes, noEnvironmentfields.Fixes: #64326