Skip to content

Commit 3ee99f5

Browse files
authored
fix(server): clean sigint handler on shutdown (#72)
1 parent fb78d63 commit 3ee99f5

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

src/__tests__/server.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe('runServer', () => {
2626
let mockHttpHandle: HttpServerHandle;
2727
let mockClose: jest.Mock;
2828
let processOnSpy: jest.SpyInstance;
29+
let processOffSpy: jest.SpyInstance;
2930

3031
beforeEach(() => {
3132
jest.clearAllMocks();
@@ -51,15 +52,17 @@ describe('runServer', () => {
5152

5253
MockStartHttpTransport.mockResolvedValue(mockHttpHandle);
5354

54-
// Spy on process.on method
55+
// Spy on process methods
5556
processOnSpy = jest.spyOn(process, 'on').mockImplementation();
57+
processOffSpy = jest.spyOn(process, 'off');
5658

5759
// Mock process.exit to prevent Jest from exiting
5860
jest.spyOn(process, 'exit').mockImplementation((() => {}) as never);
5961
});
6062

6163
afterEach(() => {
6264
processOnSpy.mockRestore();
65+
processOffSpy.mockRestore();
6366
// Note: We don't call jest.restoreAllMocks() here as it would clear module mocks
6467
// The memoization cache persists across tests, which is expected behavior
6568
});
@@ -175,6 +178,7 @@ describe('runServer', () => {
175178

176179
await serverInstance.stop();
177180

181+
expect(processOffSpy).toHaveBeenCalledWith('SIGINT', expect.any(Function));
178182
expect(serverInstance.isRunning()).toBe(false);
179183
expect({
180184
events: MockLog.info.mock.calls

src/server.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ const runServer = async (options: ServerOptions = getOptions(), {
129129
let transport: StdioServerTransport | null = null;
130130
let httpHandle: HttpServerHandle | null = null;
131131
let unsubscribeServerLogger: (() => void) | null = null;
132+
let sigintHandler: (() => void) | null = null;
132133
let running = false;
133134
let onLogSetup: ServerOnLog = () => () => {};
134135

@@ -144,6 +145,11 @@ const runServer = async (options: ServerOptions = getOptions(), {
144145
httpHandle = null;
145146
}
146147

148+
if (sigintHandler) {
149+
process.off('SIGINT', sigintHandler);
150+
sigintHandler = null;
151+
}
152+
147153
log.debug('...closing Server');
148154
await server?.close();
149155
running = false;
@@ -246,10 +252,11 @@ const runServer = async (options: ServerOptions = getOptions(), {
246252
})));
247253
});
248254

249-
if (enableSigint) {
250-
process.on('SIGINT', () => {
255+
if (enableSigint && !sigintHandler) {
256+
sigintHandler = () => {
251257
void stopServer();
252-
});
258+
};
259+
process.on('SIGINT', sigintHandler);
253260
}
254261

255262
if (options.isHttp) {

0 commit comments

Comments
 (0)