Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix: remove process listeners after stopping the server (#4013)
  • Loading branch information
snitin315 committed Nov 12, 2021
1 parent 67b52c9 commit d198e4e
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 24 deletions.
64 changes: 43 additions & 21 deletions lib/Server.js
Expand Up @@ -32,6 +32,7 @@ class Server {

this.options = options;
this.staticWatchers = [];
this.listeners = [];
// Keep track of websocket proxies for external websocket upgrade.
this.webSocketProxies = [];
this.sockets = [];
Expand Down Expand Up @@ -1168,15 +1169,11 @@ class Server {

let needForceShutdown = false;

const exitProcess = () => {
// eslint-disable-next-line no-process-exit
process.exit();
};

signals.forEach((signal) => {
process.on(signal, () => {
const listener = () => {
if (needForceShutdown) {
exitProcess();
// eslint-disable-next-line no-process-exit
process.exit();
}

this.logger.info(
Expand All @@ -1187,12 +1184,20 @@ class Server {

this.stopCallback(() => {
if (typeof this.compiler.close === "function") {
this.compiler.close(exitProcess);
this.compiler.close(() => {
// eslint-disable-next-line no-process-exit
process.exit();
});
} else {
exitProcess();
// eslint-disable-next-line no-process-exit
process.exit();
}
});
});
};

this.listeners.push({ name: signal, listener });

process.on(signal, listener);
});
}

Expand Down Expand Up @@ -1712,22 +1717,25 @@ class Server {
);
}

runBonjour() {
const bonjour = require("bonjour")();
stopBonjour(callback = () => {}) {
this.bonjour.unpublishAll(() => {
this.bonjour.destroy();

if (callback) {
callback();
}
});
}

bonjour.publish({
runBonjour() {
this.bonjour = require("bonjour")();
this.bonjour.publish({
name: `Webpack Dev Server ${os.hostname()}:${this.options.port}`,
port: this.options.port,
type: this.options.server.type === "http" ? "http" : "https",
subtypes: ["webpack"],
...this.options.bonjour,
});

process.on("exit", () => {
bonjour.unpublishAll(() => {
bonjour.destroy();
});
});
}

logStatus() {
Expand Down Expand Up @@ -2198,13 +2206,21 @@ class Server {
}
}

startCallback(callback) {
startCallback(callback = () => {}) {
this.start()
.then(() => callback(null), callback)
.catch(callback);
}

async stop() {
if (this.bonjour) {
await new Promise((resolve) => {
this.stopBonjour(() => {
resolve();
});
});
}

this.webSocketProxies = [];

await Promise.all(this.staticWatchers.map((watcher) => watcher.close()));
Expand Down Expand Up @@ -2258,9 +2274,15 @@ class Server {
this.middleware = null;
}
}

// We add listeners to signals when creating a new Server instance
// So ensure they are removed to prevent EventEmitter memory leak warnings
for (const item of this.listeners) {
process.removeListener(item.name, item.listener);
}
}

stopCallback(callback) {
stopCallback(callback = () => {}) {
this.stop()
.then(() => callback(null), callback)
.catch(callback);
Expand Down
40 changes: 37 additions & 3 deletions test/e2e/bonjour.test.js
Expand Up @@ -8,8 +8,17 @@ const runBrowser = require("../helpers/run-browser");
const port = require("../ports-map").bonjour;

describe("bonjour option", () => {
const mockPublish = jest.fn();
const mockUnpublishAll = jest.fn();
let mockPublish;
let mockUnpublishAll;
let mockDestroy;

beforeEach(() => {
mockPublish = jest.fn();
mockUnpublishAll = jest.fn((callback) => {
callback();
});
mockDestroy = jest.fn();
});

describe("as true", () => {
let compiler;
Expand All @@ -24,6 +33,7 @@ describe("bonjour option", () => {
return {
publish: mockPublish,
unpublishAll: mockUnpublishAll,
destroy: mockDestroy,
};
});

Expand All @@ -42,8 +52,10 @@ describe("bonjour option", () => {
afterEach(async () => {
await browser.close();
await server.stop();

mockPublish.mockReset();
mockUnpublishAll.mockReset();
mockDestroy.mockReset();
});

it("should call bonjour with correct params", async () => {
Expand All @@ -69,6 +81,7 @@ describe("bonjour option", () => {
});

expect(mockUnpublishAll).toHaveBeenCalledTimes(0);
expect(mockDestroy).toHaveBeenCalledTimes(0);

expect(response.status()).toMatchSnapshot("response status");

Expand All @@ -93,6 +106,7 @@ describe("bonjour option", () => {
return {
publish: mockPublish,
unpublishAll: mockUnpublishAll,
destroy: mockDestroy,
};
});

Expand All @@ -111,8 +125,10 @@ describe("bonjour option", () => {
afterEach(async () => {
await browser.close();
await server.stop();

mockPublish.mockReset();
mockUnpublishAll.mockReset();
mockDestroy.mockReset();
});

it("should call bonjour with 'https' type", async () => {
Expand All @@ -138,6 +154,7 @@ describe("bonjour option", () => {
});

expect(mockUnpublishAll).toHaveBeenCalledTimes(0);
expect(mockDestroy).toHaveBeenCalledTimes(0);

expect(response.status()).toMatchSnapshot("response status");

Expand All @@ -162,6 +179,7 @@ describe("bonjour option", () => {
return {
publish: mockPublish,
unpublishAll: mockUnpublishAll,
destroy: mockDestroy,
};
});

Expand All @@ -180,8 +198,10 @@ describe("bonjour option", () => {
afterEach(async () => {
await browser.close();
await server.stop();

mockPublish.mockReset();
mockUnpublishAll.mockReset();
mockDestroy.mockReset();
});

it("should call bonjour with 'https' type", async () => {
Expand All @@ -207,6 +227,7 @@ describe("bonjour option", () => {
});

expect(mockUnpublishAll).toHaveBeenCalledTimes(0);
expect(mockDestroy).toHaveBeenCalledTimes(0);

expect(response.status()).toMatchSnapshot("response status");

Expand All @@ -231,6 +252,7 @@ describe("bonjour option", () => {
return {
publish: mockPublish,
unpublishAll: mockUnpublishAll,
destroy: mockDestroy,
};
});

Expand Down Expand Up @@ -258,8 +280,10 @@ describe("bonjour option", () => {
afterEach(async () => {
await browser.close();
await server.stop();

mockPublish.mockReset();
mockUnpublishAll.mockReset();
mockDestroy.mockReset();
});

it("should apply bonjour options", async () => {
Expand All @@ -286,6 +310,7 @@ describe("bonjour option", () => {
});

expect(mockUnpublishAll).toHaveBeenCalledTimes(0);
expect(mockDestroy).toHaveBeenCalledTimes(0);

expect(response.status()).toMatchSnapshot("response status");

Expand All @@ -310,6 +335,7 @@ describe("bonjour option", () => {
return {
publish: mockPublish,
unpublishAll: mockUnpublishAll,
destroy: mockDestroy,
};
});

Expand Down Expand Up @@ -338,8 +364,10 @@ describe("bonjour option", () => {
afterEach(async () => {
await browser.close();
await server.stop();

mockPublish.mockReset();
mockUnpublishAll.mockReset();
mockDestroy.mockReset();
});

it("should apply bonjour options", async () => {
Expand All @@ -366,6 +394,7 @@ describe("bonjour option", () => {
});

expect(mockUnpublishAll).toHaveBeenCalledTimes(0);
expect(mockDestroy).toHaveBeenCalledTimes(0);

expect(response.status()).toMatchSnapshot("response status");

Expand All @@ -390,6 +419,7 @@ describe("bonjour option", () => {
return {
publish: mockPublish,
unpublishAll: mockUnpublishAll,
destroy: mockDestroy,
};
});

Expand All @@ -402,7 +432,9 @@ describe("bonjour option", () => {
type: "http",
protocol: "udp",
},
server: "https",
server: {
type: "https",
},
},
compiler
);
Expand All @@ -418,6 +450,7 @@ describe("bonjour option", () => {
afterEach(async () => {
await browser.close();
await server.stop();

mockPublish.mockReset();
mockUnpublishAll.mockReset();
});
Expand Down Expand Up @@ -446,6 +479,7 @@ describe("bonjour option", () => {
});

expect(mockUnpublishAll).toHaveBeenCalledTimes(0);
expect(mockDestroy).toHaveBeenCalledTimes(0);

expect(response.status()).toMatchSnapshot("response status");

Expand Down

0 comments on commit d198e4e

Please sign in to comment.