| 260 | |
| 261 | // An optional callback for graceful shutdown. |
| 262 | const shutdown = async () => { |
| 263 | // Send a "shutdown" message to the child process. Ideally we'd use a signal |
| 264 | // (SIGTERM) here, but that doesn't work on Windows. This is a portable way |
| 265 | // to tell the child process to exit gracefully. |
| 266 | if (runtime === 'bun') { |
| 267 | try { |
| 268 | process.kill(pid, 'SIGTERM'); |
| 269 | } catch (_err) { |
| 270 | // The process might have already exited, for example, if the application |
| 271 | // handler threw an error. Try terminating the process to be sure. |
| 272 | await treeKill(pid); |
| 273 | } |
| 274 | } else { |
| 275 | // For Node.js runtime using fork(), use IPC |
| 276 | await new Promise<void>((resolve, reject) => { |
| 277 | child.send('shutdown', err => { |
| 278 | if (err) { |
| 279 | // The process might have already exited, for example, if the application |
| 280 | // handler threw an error. Try terminating the process to be sure. |
| 281 | treeKill(pid) |
| 282 | .then(() => resolve()) |
| 283 | .catch(killErr => reject(killErr)); |
| 284 | } else { |
| 285 | resolve(); |
| 286 | } |
| 287 | }); |
| 288 | }); |
| 289 | } |
| 290 | }; |
| 291 | |
| 292 | return { port: message.value.port, pid, shutdown }; |
| 293 | } else { |