Skip to content

Commit

Permalink
feat(death): reference counting map
Browse files Browse the repository at this point in the history
  • Loading branch information
yjl9903 committed May 12, 2023
1 parent cb3b606 commit 3896072
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 19 deletions.
23 changes: 17 additions & 6 deletions packages/death/scripts/play.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import { onDeath } from '../src';

function sleep(timeout: number): Promise<void> {
return new Promise((res) => {
setTimeout(() => res(), timeout);
});
}

onDeath((sig) => {
console.log('Handler 1');
console.log(`Receive: ${sig}`);
console.log('Process is being killed');
});

const cancel = onDeath(() => {
console.log('This is removed');
});

onDeath(() => {
console.log('Handler 2');
});

cancel();

console.log('Start sleep');

await sleep(1000 * 1000);

function sleep(timeout: number): Promise<void> {
return new Promise((res) => {
setTimeout(() => res(), timeout);
});
}
53 changes: 40 additions & 13 deletions packages/death/src/death.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,15 @@ export function onDeath(

if (SIGINT) {
registerCallback('SIGINT', handlers.SIGINT);
emitter.addListener('SIGINT', callback);
cleanUps.push(() => emitter.removeListener('SIGINT', callback));
cleanUps.push(handlers.SIGINT.addCallback(callback));
}
if (SIGTERM) {
registerCallback('SIGTERM', handlers.SIGTERM);
emitter.addListener('SIGTERM', callback);
cleanUps.push(() => emitter.removeListener('SIGTERM', callback));
cleanUps.push(handlers.SIGTERM.addCallback(callback));
}
if (SIGQUIT) {
registerCallback('SIGQUIT', handlers.SIGQUIT);
emitter.addListener('SIGQUIT', callback);
cleanUps.push(() => emitter.removeListener('SIGQUIT', callback));
cleanUps.push(handlers.SIGQUIT.addCallback(callback));
}

return () => {
Expand All @@ -64,14 +61,36 @@ export function onDeath(
function registerCallback(signal: DeathSignals, handler: Handler) {
if (handler.count === 0) {
handler.count += 1;
process.on(signal, handler.handle);
process.on(signal, handler.listener);
}
}

function makeHandler(signal: DeathSignals): Handler {
const callbacks = new WeakMap<OnDeathCallback, number>();
return {
count: 0,
async handle(signal: NodeJS.Signals) {
callbacks,
addCallback(callback: OnDeathCallback) {
{
const count = callbacks.get(callback);
if (count !== undefined) {
callbacks.set(callback, count + 1);
} else {
callbacks.set(callback, 1);
emitter.addListener(signal, callback);
}
}
return () => {
const count = callbacks.get(callback);
if (count === undefined || count <= 1) {
callbacks.delete(callback);
emitter.removeListener(signal, callback);
} else {
callbacks.set(callback, count - 1);
}
};
},
async listener(signal: NodeJS.Signals) {
const listeners = emitter.listeners(signal);
const context: OnDeathContext = {
terminate: 'kill',
Expand All @@ -85,9 +104,9 @@ function makeHandler(signal: DeathSignals): Handler {
}

if (context.terminate === 'kill' || context.terminate === 'exit') {
process.removeListener('SIGINT', handlers.SIGINT.handle);
process.removeListener('SIGTERM', handlers.SIGTERM.handle);
process.removeListener('SIGQUIT', handlers.SIGQUIT.handle);
process.removeListener('SIGINT', handlers.SIGINT.listener);
process.removeListener('SIGTERM', handlers.SIGTERM.listener);
process.removeListener('SIGQUIT', handlers.SIGQUIT.listener);
if (context.terminate === 'kill') {
process.kill(process.pid, context.kill);
} else {
Expand All @@ -99,7 +118,15 @@ function makeHandler(signal: DeathSignals): Handler {
}

interface Handler {
handle: NodeJS.SignalsListener;

// Listener reference counting
count: number;

// process.on(SIGNAL) listener
listener: NodeJS.SignalsListener;

// Callbacks reference counting
callbacks: WeakMap<OnDeathCallback, number>;

// Add callback, and return cleanUp function
addCallback: (callback: OnDeathCallback) => () => void;
}

0 comments on commit 3896072

Please sign in to comment.