Skip to content

Commit a73f58b

Browse files
authored
fix(node): Consider tracing error handler for process exit (#7558)
1 parent baff7dd commit a73f58b

File tree

2 files changed

+23
-12
lines changed

2 files changed

+23
-12
lines changed

packages/core/src/tracing/errors.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ function errorCallback(): void {
2929
activeTransaction.setStatus(status);
3030
}
3131
}
32+
33+
// The function name will be lost when bundling but we need to be able to identify this listener later to maintain the
34+
// node.js default exit behaviour
35+
errorCallback.tag = 'sentry_tracingErrorCallback';

packages/node/src/integrations/onuncaughtexception.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import { logAndExitProcess } from './utils/errorhandling';
88

99
type OnFatalErrorHandler = (firstError: Error, secondError?: Error) => void;
1010

11+
type TaggedListener = NodeJS.UncaughtExceptionListener & {
12+
tag?: string;
13+
};
14+
1115
// CAREFUL: Please think twice before updating the way _options looks because the Next.js SDK depends on it in `index.server.ts`
1216
interface OnUncaughtExceptionOptions {
1317
// TODO(v8): Evaluate whether we should switch the default behaviour here.
@@ -95,18 +99,21 @@ export class OnUncaughtException implements Integration {
9599
// exit behaviour of the SDK accordingly:
96100
// - If other listeners are attached, do not exit.
97101
// - If the only listener attached is ours, exit.
98-
const userProvidedListenersCount = global.process
99-
.listeners('uncaughtException')
100-
.reduce<number>((acc, listener) => {
101-
if (
102-
listener.name === 'domainUncaughtExceptionClear' || // as soon as we're using domains this listener is attached by node itself
103-
listener === this.handler // filter the handler we registered ourselves)
104-
) {
105-
return acc;
106-
} else {
107-
return acc + 1;
108-
}
109-
}, 0);
102+
const userProvidedListenersCount = (
103+
global.process.listeners('uncaughtException') as TaggedListener[]
104+
).reduce<number>((acc, listener) => {
105+
if (
106+
// There are 3 listeners we ignore:
107+
listener.name === 'domainUncaughtExceptionClear' || // as soon as we're using domains this listener is attached by node itself
108+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
109+
(listener.tag && listener.tag === 'sentry_tracingErrorCallback') || // the handler we register for tracing
110+
listener === this.handler // the handler we register in this integration
111+
) {
112+
return acc;
113+
} else {
114+
return acc + 1;
115+
}
116+
}, 0);
110117

111118
const processWouldExit = userProvidedListenersCount === 0;
112119
const shouldApplyFatalHandlingLogic = this._options.exitEvenIfOtherHandlersAreRegistered || processWouldExit;

0 commit comments

Comments
 (0)