Skip to content

Leaking node signal listener after server.stop() #503

Description

@aMOPel

Describe the bug
Currently you're adding a signal listener for SIGINT to the servers process when calling server.start():

process.on("SIGINT", () => {

However this listener is never removed when calling server.stop() over the js api, effectively leaking it.

To Reproduce
I only noticed this because I was writing deno tests with this your great library and deno tests do some sanitazing checks:

https://docs.deno.com/runtime/fundamentals/testing/#sanitizers

Here is a minimal reproduction:

import { assert } from "@std/assert";
import { createServer } from "npm:@mocks-server/main";

async function initMockServer(routes: any, collections: any) {
    const server = createServer();
    await server.start()
    const { loadRoutes, loadCollections } = server.mock.createLoaders();
    loadRoutes(routes);
    loadCollections(collections);
    return server;
}

const fixtures = {
    routes: [
        {
            id: "get-users",
            url: "/api/users",
            method: "GET",
            variants: [
                {
                    id: "success",
                    type: "json",
                    options: {
                        status: 200,
                        body: { hi: "hi" },
                    },
                },
            ],
        },
    ],

    collections: [
        {
            id: "base",
            routes: ["get-users:success"],
        },
    ],
};

Deno.test("test", async (t) => {
    const server = await initMockServer(fixtures.routes, fixtures.collections);

    await server.mock.collections.select("base");
    assert(true, "works")

    await server.stop();
});
  1. mkdir -p ~/bug-repro && cd ~/bug-repro
  2. deno init
  3. paste code above into main_test.ts
  4. deno test --allow-all --trace-leaks

It will print something along these lines:

running 1 test from ./main_test.ts
test ...
------- output -------
14:41:49:76 [info][config] Configuration loaded
14:41:49:80 [info][server] Server started and listening at http://localhost:3100
14:41:49:80 [info][plugins:adminApi:server] Server started and listening at http://localhost:3110
14:41:49:81 [warn][alerts:collections] Option 'mock.collections.selected' was not defined. Selecting the first collection found
14:41:49:82 [info][mock] Selected collection: 'base'
14:41:49:82 [info][mock] Selected collection: 'base'
14:41:49:82 [info][server] Server stopped
14:41:49:82 [info][plugins:adminApi:server] Server stopped
----- output end -----
test ... FAILED (260ms)

 ERRORS

test => ./main_test.ts:40:6
error: Leaks detected:
  - A signal listener was created during the test, but not fired/cleared during the test. Clear the signal listener by calling `Deno.removeSignalListener`.
  - An async operation to get the next signal was started in this test, but never completed. This is often caused by not un-registering a OS signal handler. The operation was started here:
    at op_signal_poll (ext:core/00_infra.js:250:13)
    at pollSignal (ext:runtime/40_signals.js:18:19)
    at loop (ext:runtime/40_signals.js:73:15)
    at Object.addSignalListener (ext:runtime/40_signals.js:55:5)
    at Process.on (node:process:379:12)
    at Server.init (file:///home/user/.cache/deno/npm/registry.npmjs.org/@mocks-server/core/4.0.2/src/server/Server.js:178:13)
    at Core.init (file:///home/user/.cache/deno/npm/registry.npmjs.org/@mocks-server/core/4.0.2/src/Core.js:203:24)
    at async Core.start (file:///home/user/.cache/deno/npm/registry.npmjs.org/@mocks-server/core/4.0.2/src/Core.js:209:5)
    at async initMockServer (file:///home/user/dev/temp/main_test.ts:6:5)
    at async file:///home/user/dev/temp/main_test.ts:41:20

 FAILURES

test => ./main_test.ts:40:6

FAILED | 0 passed | 1 failed (279ms)

error: Test failed

As you can see in the logs:

  • the server is stopped
  • then the test completes and does the sanitization tests and finds that a signal listener was leaked

Expected behavior
The signal listener should be removed properly when server.stop() is called.

** Operating system, Node.js an npm versions, or browser version (please complete the following information):**

$ deno --version
deno 2.1.6 (stable, release, x86_64-unknown-linux-gnu)
v8 13.0.245.12-rusty
typescript 5.6.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions