fs-write-stream-atomic icon indicating copy to clipboard operation
fs-write-stream-atomic copied to clipboard

Leak temp file when source emit error

Open mickaelmani opened this issue 9 years ago • 0 comments

When the readable stream source emit an error :

  • fs-write-stream-atomic doesn't remove the temp file.
  • fs-write-stream-atomic doesn't emit error.

This file leaks and cannot be removed.

I've write a test to illustrate this issue :

var should = require('should');
var fs = require('fs');
var fsWriteStreamAtomic = require('fs-write-stream-atomic');
var stream = require('stream');
var util = require('util');
var uuid = require('node-uuid');
var path = require('path');

function ReadableStream(options) {
  stream.Readable.call(this, options);
  this.options = options;
  this._total = options && options.total || 1000;
  this._index = 1;
}
util.inherits(ReadableStream, stream.Readable);

ReadableStream.prototype._emitError = function() {
  var self = this;
  process.nextTick(function () {
    self.emit('error', new Error('stoped stream'));
  });
};

ReadableStream.prototype._read = function() {
  var i = this._index++;
  if (i > this._total) {
    this.push(null);
  } else if(i > this.options.stopAt) {
    this._emitError();
  } else {
    var str = '' + i;
    var buf = new Buffer(str, 'ascii');
    this.push(buf);
  }
};

var DIR = path.join(__dirname, 'samples');
var FILE_TO_WRITE = path.join(DIR, 'MyTestFile.txt');

describe('Fs-write-stream-atomic: ', function() {
  it('works with no error', function(done){
    var rs = new ReadableStream({total: 1000}); 
    // A readable stream emit 1000 chars and finish with no error
    var ws = fsWriteStreamAtomic(FILE_TO_WRITE);
    rs.pipe(ws);
    ws.on('finish', function(){
      console.log('finished');
      fs.unlinkSync(FILE_TO_WRITE);
      fs.readdir(DIR, function(err, files){
        if(!err){
          for(var i=0; i< files.length; i++){
            should(files[i]).not.containEql('MyTestFile.txt');
          }
        }
        done();
      });
    });
  });

  it('leak temp file when source emit error', function(done){
    var rs = new ReadableStream({total: 1000, stopAt:600});
    // A readable stream emit error at 600 chars
    var ws = fsWriteStreamAtomic(FILE_TO_WRITE);
    rs.pipe(ws);
    ws.on('finish', function(){
      console.log('finished');
      fs.unlinkSync(FILE_TO_WRITE);
      done();
    });
    ws.on('error', function(err){
      console.log('error write stream' + err);
      done();
    });
    rs.on('error', function(err){
      console.log('error readable stream' + err);
      fs.readdir(DIR, function(err, files){
        if(!err){
          for(var i=0; i< files.length; i++){
            should(files[i]).not.containEql('MyTestFile.txt');
          }
        }
        done();
      });
    });
  });
});

When I start the test.

npm test

Result :

Fs-write-stream-atomic: 
finished
    ✓ works with no error
error readable streamError: stoped stream
    1) leak temp file when source emit error


  1 passing (37ms)
  1 failing

  1) Fs-write-stream-atomic:  leak temp file when source emit error:
     Uncaught AssertionError: expected 'MyTestFile.txt.1272449043' not to contain 'MyTestFile.txt' (false negative fail)
      at Assertion.fail (node_modules/should/lib/assertion.js:92:17)
      at Assertion.Object.defineProperty.value [as containEql] (node_modules/should/lib/assertion.js:174:17)

fs-write-stream-atomic leave a file "MyTestFile.txt.1272449043" in the directory

Fs-write-stream-atomic-on-source-emit-error.zip

mickaelmani avatar Mar 25 '16 12:03 mickaelmani