npm / cacache

npm's content-addressable cache
Other
280 stars 31 forks source link

[BUG] put.stream can crash the process with unhandled exception, even when error handler is attached #249

Closed kalinkrustev closed 1 year ago

kalinkrustev commented 1 year ago

Is there an existing issue for this?

Current Behavior

Process terminates with error:

node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[Error: EACCES: permission denied, open 'tmp/3164ed41'] {
  errno: -13,
  code: 'EACCES',
  syscall: 'open',
  path: 'tmp/3164ed41'
}

Expected Behavior

Process does not terminate and the stream error handler is called

Steps To Reproduce

Run the following script. It will change the tmp folder permission, so that an error is triggered. It can happen in other circumstances too (of of disk space, etc.) In certain cases this results in a lingering rejected promise handleContentP within lib/content/write.js In the example, such case is when the readable stream has not ended.

const {Readable} = require('stream');
const {chmod} = require('fs/promises');
const {existsSync} = require('fs');
const cacache = require('cacache');

const read = (...params) => new Readable({
    read(size) {
        if (params.length) this.push(params.shift());
    }
});

require('http').createServer().listen(() => console.log('listening'));

((async()=>{
    if (existsSync('./tmp')) await chmod('./tmp', 0777);
    await cacache .put('.', 'key1', '1')
    await chmod('./tmp', 0555);
    return read('2').pipe(cacache.put.stream('.', 'key2')).on('error', console.error);

})()).catch(console.error);

Environment