mirror of
https://github.com/fuse-friends/fuse-native
synced 2024-10-27 18:34:01 +00:00
Add safe mode with timeouts
This commit is contained in:
parent
2c8540a571
commit
11be64ab33
86
index.js
86
index.js
@ -13,6 +13,8 @@ var IS_OSX = os.platform() === 'darwin'
|
||||
var OSX_FOLDER_ICON = '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericFolderIcon.icns'
|
||||
var HAS_FOLDER_ICON = IS_OSX && fs.existsSync(OSX_FOLDER_ICON)
|
||||
|
||||
const TIMED_OUT = Symbol('TIMED_OUT')
|
||||
|
||||
var FuseBuffer = function () {
|
||||
this.length = 0
|
||||
this.parent = undefined
|
||||
@ -36,11 +38,16 @@ exports.context = function () {
|
||||
exports.mount = function (mnt, ops, opts, cb) {
|
||||
if (typeof opts === 'function') return exports.mount(mnt, ops, null, opts)
|
||||
if (!cb) cb = noop
|
||||
var destroyed = false
|
||||
|
||||
ops = xtend(ops, opts) // clone
|
||||
if (/\*|(^,)fuse-bindings(,$)/.test(process.env.DEBUG)) ops.options = ['debug'].concat(ops.options || [])
|
||||
mnt = path.resolve(mnt)
|
||||
|
||||
if (opts && (opts.safe || opts.timeout)) {
|
||||
var stopTimeouts = wrapSafe(ops, opts.timeout || 3000)
|
||||
}
|
||||
|
||||
if (ops.displayFolder && IS_OSX) { // only works on osx
|
||||
if (!ops.options) ops.options = []
|
||||
ops.options.push('volname=' + path.basename(mnt))
|
||||
@ -49,7 +56,7 @@ exports.mount = function (mnt, ops, opts, cb) {
|
||||
|
||||
var callback = function (err) {
|
||||
callback = noop
|
||||
setImmediate(cb.bind(null, err))
|
||||
setImmediate(cb.bind(null, err, destroy))
|
||||
}
|
||||
|
||||
var init = ops.init || call
|
||||
@ -92,6 +99,15 @@ exports.mount = function (mnt, ops, opts, cb) {
|
||||
|
||||
if (!ops.force) return mount()
|
||||
exports.unmount(mnt, mount)
|
||||
|
||||
function destroy (cb) {
|
||||
if (destroyed) return null
|
||||
destroyed = true
|
||||
if (stopTimeouts) stopTimeouts()
|
||||
return exports.unmount(mnt, err => {
|
||||
return cb(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
exports.unmount = function (mnt, cb) {
|
||||
@ -116,6 +132,74 @@ exports.errno = function (code) {
|
||||
return (code && exports[code.toUpperCase()]) || -1
|
||||
}
|
||||
|
||||
function wrapSafe (ops, timeout) {
|
||||
const pending = []
|
||||
var timeoutChecker = setInterval(checkTimeouts, timeout / 4)
|
||||
var destroyed = false
|
||||
|
||||
const wrapped = {}
|
||||
for (const name of Object.keys(ops)) {
|
||||
const op = ops[name]
|
||||
|
||||
if (typeof op !== 'function') {
|
||||
wrapped[name] = op
|
||||
continue
|
||||
}
|
||||
wrapped[name] = wrapOp(op)
|
||||
}
|
||||
|
||||
Object.assign(ops, wrapped)
|
||||
return destroy
|
||||
|
||||
function wrapOp (op) {
|
||||
return function () {
|
||||
const cb = arguments[arguments.length - 1]
|
||||
var called = false
|
||||
|
||||
const idx = pending.indexOf(null)
|
||||
|
||||
const cbInfo = { cb, tick: 0 }
|
||||
pending[idx === -1 ? pending.length : idx] = cbInfo
|
||||
|
||||
try {
|
||||
op.apply(null, [...Array.prototype.slice.call(arguments, 0, -1), safeCb])
|
||||
} catch (err) {
|
||||
if (!cb[TIMED_OUT] && !called) return cb(exports.EIO)
|
||||
}
|
||||
|
||||
function safeCb () {
|
||||
called = true
|
||||
pending[pending.indexOf(cbInfo)] = null
|
||||
if (!cb[TIMED_OUT]) cb.apply(null, arguments)
|
||||
cb[TIMED_OUT] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkTimeouts () {
|
||||
for (const cbInfo of pending) {
|
||||
if (!cbInfo) continue
|
||||
if (++cbInfo.tick >= 4) {
|
||||
killCallback(cbInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function killCallback (cbInfo) {
|
||||
cbInfo.cb(exports.EIO)
|
||||
cbInfo.cb[TIMED_OUT] = true
|
||||
pending[pending.indexOf(cbInfo)] = null
|
||||
}
|
||||
|
||||
function destroy () {
|
||||
clearInterval(timeoutChecker)
|
||||
for (const cbInfo of [...pending]) {
|
||||
if (cbInfo) killCallback(cbInfo)
|
||||
}
|
||||
destroyed = true
|
||||
}
|
||||
}
|
||||
|
||||
exports.EPERM = -1
|
||||
exports.ENOENT = -2
|
||||
exports.ESRCH = -3
|
||||
|
Loading…
Reference in New Issue
Block a user