Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use 'close' event on file stream for reliability #787

Closed
wants to merge 1 commit into from

Conversation

Trott
Copy link
Contributor

@Trott Trott commented Oct 11, 2019

Change listened-for event on the output stream in storage/disk.js from
'finish' to 'close' to improve reliability. With 'finish', there is a
race condition such that sometimes the callback runs before the file
exists.

Refs: #238

Change listened-for event on the output stream in storage/disk.js from
'finish' to 'close' to improve reliability. With 'finish', there is a
race condition such that sometimes the callback runs before the file
exists.

Refs: expressjs#238
@Trott
Copy link
Contributor Author

Trott commented Oct 11, 2019

/ping @mcollina @ronag Does this seem like the correct event to listen for in this situation, or was the previous code correct and this is indicative of a more elusive problem?

@Trott Trott mentioned this pull request Oct 11, 2019
@ronag
Copy link

ronag commented Oct 11, 2019

That's interesting. 'finish' should be fine. I will dig into this. What version of node?

In the meantime this workaround is not entirely correct either, you might end up invoking the callback twice since 'close' will/should be emitted after 'error'. Also you are not handling the 'error' event from the source stream.

      cb = once(cb)
      var finalPath = path.join(destination, filename)
      var outStream = fs.createWriteStream(finalPath)

      file.stream.pipe(outStream)
      file.stream.on('error', err => {
        outStream.destroy()
        cb(err)
      })
      outStream.on('error', cb)
      outStream.on('close', function () {
        cb(null, {
          destination: destination,
          filename: filename,
          path: finalPath,
          size: outStream.bytesWritten
        })
      })

Also are you aware that _handleFile will not destroy/free the source stream upon failure? I'm not sure if that might cause file descriptor leaks elsewhere.

Furthermore this code assumes that the source stream has not already completed. If it has completed this will never call the callback. But I guess that's a minor.

@ronag
Copy link

ronag commented Oct 11, 2019

Yes, I think this might be a bug in node. Streams can emit 'finish' before 'open' if no data has been written before end(), thus causing a race condition.

@ronag
Copy link

ronag commented Oct 11, 2019

nodejs/node#29930

@Trott
Copy link
Contributor Author

Trott commented Oct 11, 2019

That's interesting. 'finish' should be fine. I will dig into this. What version of node?

@ronag I was using Node.js 12.11.1.

@Trott
Copy link
Contributor Author

Trott commented Oct 11, 2019

nodejs/node#29930

Awesome and thank you! I'll close this.

@Trott Trott closed this Oct 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants