bun
bun copied to clipboard
Node.js process.on compatibility
Repro:
process.on(
"unhandledRejection",
(err) => {
console.log('error' + err);
});
const foo = new Promise((resolve,reject) => {
setTimeout(() => {
reject('foo');
}, 300);
});
Error:
$ bun run /tmp/process.js
[1.16ms] "node_modules.bun" - 105 modules, 46 packages
1 | process.on("unhandledRejection", (err) => {
console.log("error" + err);
});
^
TypeError: process.on is not a function. (In 'process.on("unhandledRejection", (err) => {
console.log("error" + err);
})', 'process.on' is undefined)
at /private/tmp/process.js:1:0
hello sir, I want to work on this issue. Can you please guide me to where I can find this code inside the project?
Small update
process.on
technically works but it does not monitor the events as expected, it just extends from EventEmitter
. I am keeping this issue open because that doesn't fully address the intended issue
Thanks! At least nbb doesn't trip over that anymore: https://twitter.com/borkdude/status/1581582447661449216
The remaining issues in nbb to have a REPL are "readline"
and "vm"
support.
I'm interested in gracefully handling process exit. Right now, I noticed that some SQLite data fails to persist unless the database is gracefully closed. I'd like to do something like this:
process.on('beforeExit', () => db.close());
The SQL behavior probably warrants its own top-level issue, I suppose.
This feature is much needed; any progress on this?
Would really love if this got implemented!
I'm interested in gracefully handling process exit. Right now, I noticed that some SQLite data fails to persist unless the database is gracefully closed. I'd like to do something like this:
process.on('beforeExit', () => db.close());
The SQL behavior probably warrants its own top-level issue, I suppose.
This has been fixed in canary (and will land in Bun v0.6.14)
beforeExit
, exit
have both landed in canary as well and tomorrow signal handlers will too.
unhandledRejection
will not land in this canary
Hello,
// @ts-ignore
process.on('beforeExit', () => console.log('beforeExit'));
// @ts-ignore
process.on('exit', () => console.log('exit'));
// without ts-ignore, we get "Property 'on' does not exist on type 'Process'.ts(2339)"
None of them are called in 0.7.0 after pressing CTRL+C, is that expected?
None of them are called in 0.7.0 after pressing CTRL+C, is that expected?
Yes, that is consistent with Node.js:
@baptistecs normally CTRL+C is intercepted by your terminal tty driver and it usually sends an interrupt signal (SIGINT). You could do something like:
process.on('SIGINT', ...);
I often use it for closing a database connection when exiting the sever process like so (as in the better-sqlite3 docs):
process.on('exit', () => db.close());
process.on('SIGHUP', () => process.exit(128 + 1)); // hang up
process.on('SIGINT', () => process.exit(128 + 2)); // ctrl+c
process.on('SIGTERM', () => process.exit(128 + 15)); // kill
Although I'm not sure it works in bun yet. The process.on() handlers should get called, so see if it works for you.
Thank you @maxmilton!
I confirm, this is working:
process.on("SIGINT", () => {
console.log('EXIT');
process.exit(0);
});
Unfortunately, this will not be fixed by bun.js is not suitable for large projects, because without these signals it is impossible to make a normal error handler 😔
Please add unhandledRejection and uncaughtException I'll be waiting. Until then, I will use Bun only as a package manager.
Same issue here. Example:
process.on('uncaughtException', function(err){
console.log("caught2")
})
try {
setTimeout(() => {
throw new Error("error")
}, 1000)
await new Promise((resolve) => setTimeout(resolve, 3000))
console.log("done")
} catch(e) {
console.log("caught")
}
Throws error on Bun, prints caught2 on node.
Multiple event/signal handlers are missing for WinOS.
// t-events-signals.js
// ...works in NodeJS...
// Signal events
[`SIGBREAK`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, catchSignal.bind(null, eventType));
});
// IPC events
[`disconnect`, `message`].forEach((eventType) => {
process.on(eventType, catchEvent.bind(null, eventType));
});
// Process exceptions and promise rejection events
[`uncaughtException`, `unhandledRejection`, `rejectionHandled`, `warning`].forEach((eventType) => {
process.on(eventType, catchEvent.bind(null, eventType));
});
// Process exit events
[`beforeExit`, `exit`].forEach((eventType) => {
process.on(eventType, catchExit.bind(null, eventType));
});
// Process worker event
[`worker`].forEach((eventType) => {
process.on(eventType, (exitCode) => catchEvent.bind(null, eventType)(exitCode));
});
function catchSignal(eventType) {
// upon a SIGINT, parent/shell may display a '^C'
// * use an initial '\r' to reset line position, allowing overwrite of any initial '^C'
console.log('\r' + 'Caught signal...', { eventType });
}
function catchEvent(eventType) {
console.log('Caught event...', { eventType });
}
function catchExit(eventType, exitCode) {
console.log('Now exiting...', { eventType }, { exitCode });
}
// emit unhandledRejection
const _foo = new Promise((_resolve, reject) => {
setTimeout(() => {
reject('foo');
}, 300);
});
// emit uncaughtException
setTimeout(() => {
throw ('bar');
}, 500);
setTimeout(() => {
console.log('The service is now finished.');
}, 2000);
Note that NodeJS catches all SIGBREAKS and SIGINTS and the uncaught/unhandled errors, ending with an exit code of 0
.
> node "t-events-signals.js"
Caught event... { eventType: 'unhandledRejection' }
Caught event... { eventType: 'uncaughtException' }
Caught signal... { eventType: 'SIGINT' }
Caught signal... { eventType: 'SIGINT' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGINT' }
The service is now finished.
Now exiting... { eventType: 'beforeExit' } { exitCode: 0 }
Now exiting... { eventType: 'exit' } { exitCode: 0 }
bun
exits with errors and only catches the beforeExit
and exit
events and ends with a 1
error exit code.
> bun run "t-events-signals.js"
error: foo
Now exiting... {
eventType: "beforeExit",
} {
exitCode: 0,
}
Now exiting... {
eventType: "exit",
} {
exitCode: 1,
}
``
bun --watch just logs all throws, I wonder if it is possible to implement a similar interception of throws by a listener. Such a badly needed feature.
+1, I need this feature for my discord bot shard to not restart on every uncaught thrown exception
+1 for the reason above
+1 because alongside with this issue https://github.com/oven-sh/bun/issues/9629 these features are very needed.
+1 for I'm going to write a game server based on bun. I need to log uncaught exceptions
+1
we'll add this a little after bun v1.1
This will be shipped in Bun v1.1.8, which releases in a couple hours from this comment.
To get it now:
bun upgrade --canary
Thanks for the improvements! Most of the signals are now being caught. For WinOS, 'SIGBREAK' is still being missed and causing process exceptions/panics.