mirror of
https://github.com/fuse-friends/fuse-native
synced 2024-10-27 18:34:01 +00:00
malloc and track thread_local buffers from js (#20)
* malloc and track thread_local buffers from js to avoid crashes when multiple external buffers are made from the same pointer * make tests pass on 14.3.0 * disable npm cache * debug log * detach array buffer on read free as a test * fix detatch * detach arraybuffer asap, to avoid crashes * reset test * add secure travis key * missing arraybuffer pass * bump all the flags * no linux 32
This commit is contained in:
parent
519b468995
commit
e218d40f90
15
.travis.yml
15
.travis.yml
@ -33,5 +33,18 @@ before_deploy:
|
|||||||
- ARCHIVE_NAME="${TRAVIS_TAG:-latest}-$TRAVIS_OS_NAME.tar"
|
- ARCHIVE_NAME="${TRAVIS_TAG:-latest}-$TRAVIS_OS_NAME.tar"
|
||||||
- npm run prebuild
|
- npm run prebuild
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then PREBUILD_ARCH=ia32 npm run prebuild; fi
|
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then PREBUILD_ARCH=ia32 npm run prebuild; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then PREBUILD_ARCH=ia32 npm run prebuild; fi
|
|
||||||
- cd prebuilds && tar cvf "../$ARCHIVE_NAME" . && cd ..
|
- cd prebuilds && tar cvf "../$ARCHIVE_NAME" . && cd ..
|
||||||
|
|
||||||
|
cache:
|
||||||
|
npm: false
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
provider: releases
|
||||||
|
draft: false
|
||||||
|
prerelease: true
|
||||||
|
api_key:
|
||||||
|
secure: "KPn3xR4LWcg/H259aSZh26XX0eapR88xSNUkBmEri/sCJSyZ0+asLZSv/HDD3KJP4HeuIKsQc0v8fcebD83fkvaSvlUzSppMQgniwuGC1cAefbrgZDwmJJ/n+lE8Wr9x4adOBTgICS5Uc8LlZ1PuJGm4mmequVs29BEw9738LzN4+3NpoCoWd0FAgGF0tDTsaYL1tJqERAyNIxHS+adUPe0F2r0d2UJ7mOrW7s8Ai6e6QryFsFvA2m0Xn/pQmNO/mcq+LPcw57pWuI3Hm3Cu3W8VPJXYp/yJaFqTAn3D9Fwz4tkmbfmca4ETwZYOS3lvL/rjLQ+69SJlRRu/QfPECkZven+wwsLX/DmyGHgEWqeGWjKj/NxYOIKUKEZZCVrF8cy4j9mac+LK6bAeDZERKSxUJ9GT5WsjvV3RNKgp3MZF7mtmj4IWXfgcuwFX49oIqhzSJsucBBXlB74J7Qua5VJPEAo/7X7Q+Y9IT9JHwxXsXVF5ZNj1PMlJicVD6oKi4XCFOVxSE9wdzlBwMOlUyBGhAIzS6lmxHOELYO9C7l8t/8Zvi4a+YGvOwn0dzLb9zuA1bzqJmEB1fkQMZXHvcEY1o5jSTQ0cNn1Wx4Ck9zyLyhnZ5KRXKzGQ1du55iVOThcbl/8j6zT218SiZMMtv8ZwPy4pJt4skMGsoOZtYlE=" file: "$ARCHIVE_NAME"
|
||||||
|
skip_cleanup: true
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
node: 'node'
|
||||||
|
13
binding.gyp
13
binding.gyp
@ -11,7 +11,18 @@
|
|||||||
"sources": [
|
"sources": [
|
||||||
"fuse-native.c"
|
"fuse-native.c"
|
||||||
],
|
],
|
||||||
"cflags": ["-rdynamic"]
|
'xcode_settings': {
|
||||||
|
'OTHER_CFLAGS': [
|
||||||
|
'-g',
|
||||||
|
'-O3',
|
||||||
|
'-Wall'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'cflags': [
|
||||||
|
'-g',
|
||||||
|
'-O3',
|
||||||
|
'-Wall'
|
||||||
|
],
|
||||||
}, {
|
}, {
|
||||||
"target_name": "postinstall",
|
"target_name": "postinstall",
|
||||||
"type": "none",
|
"type": "none",
|
||||||
|
104
fuse-native.c
104
fuse-native.c
@ -18,6 +18,10 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
static int IS_ARRAY_BUFFER_DETACH_SUPPORTED = 0;
|
||||||
|
|
||||||
|
napi_status napi_detach_arraybuffer(napi_env env, napi_value buf);
|
||||||
|
|
||||||
#define FUSE_NATIVE_CALLBACK(fn, blk)\
|
#define FUSE_NATIVE_CALLBACK(fn, blk)\
|
||||||
napi_env env = ft->env;\
|
napi_env env = ft->env;\
|
||||||
napi_handle_scope scope;\
|
napi_handle_scope scope;\
|
||||||
@ -43,7 +47,7 @@
|
|||||||
uint32_t op = op_##name;\
|
uint32_t op = op_##name;\
|
||||||
FUSE_NATIVE_CALLBACK(ft->handlers[op], {\
|
FUSE_NATIVE_CALLBACK(ft->handlers[op], {\
|
||||||
napi_value argv[callbackArgs + 2];\
|
napi_value argv[callbackArgs + 2];\
|
||||||
napi_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0]));\
|
napi_get_reference_value(env, l->self, &(argv[0]));\
|
||||||
napi_create_uint32(env, l->op, &(argv[1]));\
|
napi_create_uint32(env, l->op, &(argv[1]));\
|
||||||
callbackBlk\
|
callbackBlk\
|
||||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, callbackArgs + 2, argv, NULL)\
|
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, callbackArgs + 2, argv, NULL)\
|
||||||
@ -116,6 +120,7 @@ typedef struct {
|
|||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
napi_ref ctx;
|
napi_ref ctx;
|
||||||
|
napi_ref malloc;
|
||||||
|
|
||||||
// Operation handlers
|
// Operation handlers
|
||||||
napi_ref handlers[35];
|
napi_ref handlers[35];
|
||||||
@ -132,6 +137,8 @@ typedef struct {
|
|||||||
} fuse_thread_t;
|
} fuse_thread_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
napi_ref self;
|
||||||
|
|
||||||
// Opcode
|
// Opcode
|
||||||
uint32_t op;
|
uint32_t op;
|
||||||
void *op_fn;
|
void *op_fn;
|
||||||
@ -180,10 +187,6 @@ static fuse_thread_locals_t* get_thread_locals ();
|
|||||||
// Helpers
|
// Helpers
|
||||||
// TODO: Extract into a separate file.
|
// TODO: Extract into a separate file.
|
||||||
|
|
||||||
static void fin (napi_env env, void *fin_data, void* fin_hint) {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t uint32s_to_uint64 (uint32_t **ints) {
|
static uint64_t uint32s_to_uint64 (uint32_t **ints) {
|
||||||
uint64_t low = *((*ints)++);
|
uint64_t low = *((*ints)++);
|
||||||
uint64_t high = *((*ints)++);
|
uint64_t high = *((*ints)++);
|
||||||
@ -367,7 +370,7 @@ FUSE_METHOD_VOID(releasedir, 2, 0, (const char *path, struct fuse_file_info *inf
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
FUSE_METHOD(read, 6, 1, (const char *path, char *buf, size_t len, off_t offset, struct fuse_file_info *info), {
|
FUSE_METHOD(read, 6, 2, (const char *path, char *buf, size_t len, off_t offset, struct fuse_file_info *info), {
|
||||||
l->path = path;
|
l->path = path;
|
||||||
l->buf = buf;
|
l->buf = buf;
|
||||||
l->len = len;
|
l->len = len;
|
||||||
@ -376,14 +379,14 @@ FUSE_METHOD(read, 6, 1, (const char *path, char *buf, size_t len, off_t offset,
|
|||||||
}, {
|
}, {
|
||||||
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
napi_create_uint32(env, l->info->fh, &(argv[3]));
|
napi_create_uint32(env, l->info->fh, &(argv[3]));
|
||||||
napi_create_external_buffer(env, l->len, (char *) l->buf, &fin, NULL, &(argv[4]));
|
napi_create_external_buffer(env, l->len, (char *) l->buf, NULL, NULL, &(argv[4]));
|
||||||
napi_create_uint32(env, l->len, &(argv[5]));
|
napi_create_uint32(env, l->len, &(argv[5]));
|
||||||
FUSE_UINT64_TO_INTS_ARGV(l->offset, 6)
|
FUSE_UINT64_TO_INTS_ARGV(l->offset, 6)
|
||||||
}, {
|
}, {
|
||||||
// TODO: handle bytes processed?
|
if (IS_ARRAY_BUFFER_DETACH_SUPPORTED == 1) assert(napi_detach_arraybuffer(env, argv[3]) == napi_ok);
|
||||||
})
|
})
|
||||||
|
|
||||||
FUSE_METHOD(write, 6, 1, (const char *path, const char *buf, size_t len, off_t offset, struct fuse_file_info *info), {
|
FUSE_METHOD(write, 6, 2, (const char *path, const char *buf, size_t len, off_t offset, struct fuse_file_info *info), {
|
||||||
l->path = path;
|
l->path = path;
|
||||||
l->buf = buf;
|
l->buf = buf;
|
||||||
l->len = len;
|
l->len = len;
|
||||||
@ -392,11 +395,11 @@ FUSE_METHOD(write, 6, 1, (const char *path, const char *buf, size_t len, off_t o
|
|||||||
}, {
|
}, {
|
||||||
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
napi_create_uint32(env, l->info->fh, &(argv[3]));
|
napi_create_uint32(env, l->info->fh, &(argv[3]));
|
||||||
napi_create_external_buffer(env, l->len, (char *) l->buf, &fin, NULL, &(argv[4]));
|
napi_create_external_buffer(env, l->len, (char *) l->buf, NULL, NULL, &(argv[4]));
|
||||||
napi_create_uint32(env, l->len, &(argv[5]));
|
napi_create_uint32(env, l->len, &(argv[5]));
|
||||||
FUSE_UINT64_TO_INTS_ARGV(l->offset, 6)
|
FUSE_UINT64_TO_INTS_ARGV(l->offset, 6)
|
||||||
}, {
|
}, {
|
||||||
// TODO: handle bytes processed?
|
if (IS_ARRAY_BUFFER_DETACH_SUPPORTED == 1) assert(napi_detach_arraybuffer(env, argv[3]) == napi_ok);
|
||||||
})
|
})
|
||||||
|
|
||||||
FUSE_METHOD(readdir, 1, 2, (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info), {
|
FUSE_METHOD(readdir, 1, 2, (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info), {
|
||||||
@ -446,7 +449,7 @@ FUSE_METHOD(readdir, 1, 2, (const char *path, void *buf, fuse_fill_dir_t filler,
|
|||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
|
||||||
FUSE_METHOD_VOID(setxattr, 5, 0, (const char *path, const char *name, const char *value, size_t size, int flags, uint32_t position), {
|
FUSE_METHOD(setxattr, 5, 1, (const char *path, const char *name, const char *value, size_t size, int flags, uint32_t position), {
|
||||||
l->path = path;
|
l->path = path;
|
||||||
l->name = name;
|
l->name = name;
|
||||||
l->value = value;
|
l->value = value;
|
||||||
@ -456,12 +459,14 @@ FUSE_METHOD_VOID(setxattr, 5, 0, (const char *path, const char *name, const char
|
|||||||
}, {
|
}, {
|
||||||
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
||||||
napi_create_external_buffer(env, l->size, (char *) l->value, &fin, NULL, &(argv[4]));
|
napi_create_external_buffer(env, l->size, (char *) l->value, NULL, NULL, &(argv[4]));
|
||||||
napi_create_uint32(env, l->position, &(argv[5]));
|
napi_create_uint32(env, l->position, &(argv[5]));
|
||||||
napi_create_uint32(env, l->flags, &(argv[6]));
|
napi_create_uint32(env, l->flags, &(argv[6]));
|
||||||
|
}, {
|
||||||
|
if (IS_ARRAY_BUFFER_DETACH_SUPPORTED == 1) assert(napi_detach_arraybuffer(env, argv[2]) == napi_ok);
|
||||||
})
|
})
|
||||||
|
|
||||||
FUSE_METHOD_VOID(getxattr, 4, 0, (const char *path, const char *name, char *value, size_t size, uint32_t position), {
|
FUSE_METHOD(getxattr, 4, 1, (const char *path, const char *name, char *value, size_t size, uint32_t position), {
|
||||||
l->path = path;
|
l->path = path;
|
||||||
l->name = name;
|
l->name = name;
|
||||||
l->value = value;
|
l->value = value;
|
||||||
@ -470,13 +475,15 @@ FUSE_METHOD_VOID(getxattr, 4, 0, (const char *path, const char *name, char *valu
|
|||||||
}, {
|
}, {
|
||||||
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
||||||
napi_create_external_buffer(env, l->size, (char *) l->value, &fin, NULL, &(argv[4]));
|
napi_create_external_buffer(env, l->size, (char *) l->value, NULL, NULL, &(argv[4]));
|
||||||
napi_create_uint32(env, l->position, &(argv[5]));
|
napi_create_uint32(env, l->position, &(argv[5]));
|
||||||
|
}, {
|
||||||
|
if (IS_ARRAY_BUFFER_DETACH_SUPPORTED == 1) assert(napi_detach_arraybuffer(env, argv[2]) == napi_ok);
|
||||||
})
|
})
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
FUSE_METHOD_VOID(setxattr, 5, 0, (const char *path, const char *name, const char *value, size_t size, int flags), {
|
FUSE_METHOD(setxattr, 5, 1, (const char *path, const char *name, const char *value, size_t size, int flags), {
|
||||||
l->path = path;
|
l->path = path;
|
||||||
l->name = name;
|
l->name = name;
|
||||||
l->value = value;
|
l->value = value;
|
||||||
@ -485,12 +492,14 @@ FUSE_METHOD_VOID(setxattr, 5, 0, (const char *path, const char *name, const char
|
|||||||
}, {
|
}, {
|
||||||
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
||||||
napi_create_external_buffer(env, l->size, (char *) l->value, &fin, NULL, &(argv[4]));
|
napi_create_external_buffer(env, l->size, (char *) l->value, NULL, NULL, &(argv[4]));
|
||||||
napi_create_uint32(env, 0, &(argv[5])); // normalize apis between mac and linux
|
napi_create_uint32(env, 0, &(argv[5])); // normalize apis between mac and linux
|
||||||
napi_create_uint32(env, l->flags, &(argv[6]));
|
napi_create_uint32(env, l->flags, &(argv[6]));
|
||||||
|
}, {
|
||||||
|
if (IS_ARRAY_BUFFER_DETACH_SUPPORTED == 1) assert(napi_detach_arraybuffer(env, argv[2]) == napi_ok);
|
||||||
})
|
})
|
||||||
|
|
||||||
FUSE_METHOD_VOID(getxattr, 4, 0, (const char *path, const char *name, char *value, size_t size), {
|
FUSE_METHOD(getxattr, 4, 1, (const char *path, const char *name, char *value, size_t size), {
|
||||||
l->path = path;
|
l->path = path;
|
||||||
l->name = name;
|
l->name = name;
|
||||||
l->value = value;
|
l->value = value;
|
||||||
@ -498,19 +507,23 @@ FUSE_METHOD_VOID(getxattr, 4, 0, (const char *path, const char *name, char *valu
|
|||||||
}, {
|
}, {
|
||||||
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
napi_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
|
||||||
napi_create_external_buffer(env, l->size, (char *) l->value, &fin, NULL, &(argv[4]));
|
napi_create_external_buffer(env, l->size, (char *) l->value, NULL, NULL, &(argv[4]));
|
||||||
napi_create_uint32(env, 0, &(argv[5]));
|
napi_create_uint32(env, 0, &(argv[5]));
|
||||||
|
}, {
|
||||||
|
if (IS_ARRAY_BUFFER_DETACH_SUPPORTED == 1) assert(napi_detach_arraybuffer(env, argv[2]) == napi_ok);
|
||||||
})
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FUSE_METHOD_VOID(listxattr, 2, 0, (const char *path, char *list, size_t size), {
|
FUSE_METHOD(listxattr, 2, 1, (const char *path, char *list, size_t size), {
|
||||||
l->path = path;
|
l->path = path;
|
||||||
l->list = list;
|
l->list = list;
|
||||||
l->size = size;
|
l->size = size;
|
||||||
}, {
|
}, {
|
||||||
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
napi_create_external_buffer(env, l->size, l->list, &fin, NULL, &(argv[3]));
|
napi_create_external_buffer(env, l->size, l->list, NULL, NULL, &(argv[3]));
|
||||||
|
}, {
|
||||||
|
if (IS_ARRAY_BUFFER_DETACH_SUPPORTED == 1) assert(napi_detach_arraybuffer(env, argv[2]) == napi_ok);
|
||||||
})
|
})
|
||||||
|
|
||||||
FUSE_METHOD_VOID(removexattr, 2, 0, (const char *path, const char *name), {
|
FUSE_METHOD_VOID(removexattr, 2, 0, (const char *path, const char *name), {
|
||||||
@ -670,8 +683,10 @@ FUSE_METHOD_VOID(rmdir, 1, 0, (const char *path), {
|
|||||||
static void fuse_native_dispatch_init (uv_async_t* handle, fuse_thread_locals_t* l, fuse_thread_t* ft) {\
|
static void fuse_native_dispatch_init (uv_async_t* handle, fuse_thread_locals_t* l, fuse_thread_t* ft) {\
|
||||||
FUSE_NATIVE_CALLBACK(ft->handlers[op_init], {
|
FUSE_NATIVE_CALLBACK(ft->handlers[op_init], {
|
||||||
napi_value argv[2];
|
napi_value argv[2];
|
||||||
napi_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0]));
|
|
||||||
|
napi_get_reference_value(env, l->self, &(argv[0]));
|
||||||
napi_create_uint32(env, l->op, &(argv[1]));
|
napi_create_uint32(env, l->op, &(argv[1]));
|
||||||
|
|
||||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 2, argv, NULL);
|
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 2, argv, NULL);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -687,10 +702,13 @@ NAPI_METHOD(fuse_native_signal_init) {
|
|||||||
|
|
||||||
static void * fuse_native_init (struct fuse_conn_info *conn) {
|
static void * fuse_native_init (struct fuse_conn_info *conn) {
|
||||||
fuse_thread_locals_t *l = get_thread_locals();
|
fuse_thread_locals_t *l = get_thread_locals();
|
||||||
|
|
||||||
l->op = op_init;
|
l->op = op_init;
|
||||||
l->op_fn = fuse_native_dispatch_init;
|
l->op_fn = fuse_native_dispatch_init;
|
||||||
|
|
||||||
uv_async_send(&(l->async));
|
uv_async_send(&(l->async));
|
||||||
uv_sem_wait(&(l->sem));
|
uv_sem_wait(&(l->sem));
|
||||||
|
|
||||||
return l->fuse;
|
return l->fuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,12 +718,27 @@ static void fuse_native_dispatch (uv_async_t* handle) {
|
|||||||
fuse_thread_locals_t *l = (fuse_thread_locals_t *) handle->data;
|
fuse_thread_locals_t *l = (fuse_thread_locals_t *) handle->data;
|
||||||
fuse_thread_t *ft = l->fuse;
|
fuse_thread_t *ft = l->fuse;
|
||||||
void (*fn)(uv_async_t *, fuse_thread_locals_t *, fuse_thread_t *) = l->op_fn;
|
void (*fn)(uv_async_t *, fuse_thread_locals_t *, fuse_thread_t *) = l->op_fn;
|
||||||
|
|
||||||
fn(handle, l, ft);
|
fn(handle, l, ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fuse_native_async_init (uv_async_t* handle) {
|
static void fuse_native_async_init (uv_async_t* handle) {
|
||||||
fuse_thread_locals_t *l = (fuse_thread_locals_t *) handle->data;
|
fuse_thread_t *ft = (fuse_thread_t *) handle->data;
|
||||||
fuse_thread_t *ft = l->fuse;
|
fuse_thread_locals_t *l;
|
||||||
|
|
||||||
|
FUSE_NATIVE_CALLBACK(ft->malloc, {
|
||||||
|
napi_value argv[1];
|
||||||
|
napi_create_uint32(ft->env, (uint32_t) sizeof(fuse_thread_locals_t), &(argv[0]));
|
||||||
|
|
||||||
|
napi_value buf;
|
||||||
|
NAPI_MAKE_CALLBACK(ft->env, NULL, ctx, callback, 1, argv, &buf);
|
||||||
|
|
||||||
|
size_t l_len;
|
||||||
|
|
||||||
|
napi_get_buffer_info(env, buf, (void **) &l, &l_len);
|
||||||
|
napi_create_reference(env, buf, 1, &(l->self));
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
int err = uv_async_init(uv_default_loop(), &(l->async), (uv_async_cb) fuse_native_dispatch);
|
int err = uv_async_init(uv_default_loop(), &(l->async), (uv_async_cb) fuse_native_dispatch);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
@ -714,6 +747,8 @@ static void fuse_native_async_init (uv_async_t* handle) {
|
|||||||
|
|
||||||
uv_sem_init(&(l->sem), 0);
|
uv_sem_init(&(l->sem), 0);
|
||||||
l->async.data = l;
|
l->async.data = l;
|
||||||
|
ft->async.data = l;
|
||||||
|
l->fuse = ft;
|
||||||
|
|
||||||
uv_sem_post(&(ft->sem));
|
uv_sem_post(&(ft->sem));
|
||||||
}
|
}
|
||||||
@ -728,18 +763,15 @@ static fuse_thread_locals_t* get_thread_locals () {
|
|||||||
return (fuse_thread_locals_t *) data;
|
return (fuse_thread_locals_t *) data;
|
||||||
}
|
}
|
||||||
|
|
||||||
fuse_thread_locals_t* l = (fuse_thread_locals_t *) malloc(sizeof(fuse_thread_locals_t));
|
|
||||||
l->fuse = ft;
|
|
||||||
|
|
||||||
// Need to lock the mutation of l->async.
|
// Need to lock the mutation of l->async.
|
||||||
uv_mutex_lock(&(ft->mut));
|
uv_mutex_lock(&(ft->mut));
|
||||||
ft->async.data = l;
|
ft->async.data = ft;
|
||||||
|
|
||||||
// Notify the main thread to uv_async_init l->async.
|
// Notify the main thread to uv_async_init l->async.
|
||||||
uv_async_send(&(ft->async));
|
uv_async_send(&(ft->async));
|
||||||
uv_sem_wait(&(ft->sem));
|
uv_sem_wait(&(ft->sem));
|
||||||
|
|
||||||
l->async.data = l;
|
fuse_thread_locals_t *l = (fuse_thread_locals_t*) ft->async.data;
|
||||||
|
|
||||||
pthread_setspecific(thread_locals_key, (void *) l);
|
pthread_setspecific(thread_locals_key, (void *) l);
|
||||||
uv_mutex_unlock(&(ft->mut));
|
uv_mutex_unlock(&(ft->mut));
|
||||||
@ -759,14 +791,15 @@ static void* start_fuse_thread (void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NAPI_METHOD(fuse_native_mount) {
|
NAPI_METHOD(fuse_native_mount) {
|
||||||
NAPI_ARGV(6)
|
NAPI_ARGV(7)
|
||||||
|
|
||||||
NAPI_ARGV_UTF8(mnt, 1024, 0);
|
NAPI_ARGV_UTF8(mnt, 1024, 0);
|
||||||
NAPI_ARGV_UTF8(mntopts, 1024, 1);
|
NAPI_ARGV_UTF8(mntopts, 1024, 1);
|
||||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_t *, ft, 2);
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_t *, ft, 2);
|
||||||
napi_create_reference(env, argv[3], 1, &(ft->ctx));
|
napi_create_reference(env, argv[3], 1, &(ft->ctx));
|
||||||
napi_value handlers = argv[4];
|
napi_create_reference(env, argv[4], 1, &(ft->malloc));
|
||||||
NAPI_ARGV_BUFFER_CAST(uint32_t *, implemented, 5)
|
napi_value handlers = argv[5];
|
||||||
|
NAPI_ARGV_BUFFER_CAST(uint32_t *, implemented, 6)
|
||||||
|
|
||||||
for (int i = 0; i < 35; i++) {
|
for (int i = 0; i < 35; i++) {
|
||||||
ft->handlers[i] = NULL;
|
ft->handlers[i] = NULL;
|
||||||
@ -869,6 +902,13 @@ NAPI_METHOD(fuse_native_unmount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NAPI_INIT() {
|
NAPI_INIT() {
|
||||||
|
const napi_node_version* version;
|
||||||
|
assert(napi_get_node_version(env, &version) == napi_ok);
|
||||||
|
|
||||||
|
if (version->major > 12 || (version->major == 12 && version->minor >= 16)) {
|
||||||
|
IS_ARRAY_BUFFER_DETACH_SUPPORTED = 1;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_key_create(&(thread_locals_key), NULL); // TODO: add destructor
|
pthread_key_create(&(thread_locals_key), NULL); // TODO: add destructor
|
||||||
|
|
||||||
NAPI_EXPORT_SIZEOF(fuse_thread_t)
|
NAPI_EXPORT_SIZEOF(fuse_thread_t)
|
||||||
|
30
index.js
30
index.js
@ -144,6 +144,7 @@ class Fuse extends Nanoresource {
|
|||||||
this._mkdir = !!opts.mkdir
|
this._mkdir = !!opts.mkdir
|
||||||
this._thread = null
|
this._thread = null
|
||||||
this._handlers = this._makeHandlerArray()
|
this._handlers = this._makeHandlerArray()
|
||||||
|
this._threads = new Set()
|
||||||
|
|
||||||
const implemented = [binding.op_init, binding.op_error, binding.op_getattr]
|
const implemented = [binding.op_init, binding.op_error, binding.op_getattr]
|
||||||
if (ops) {
|
if (ops) {
|
||||||
@ -200,6 +201,12 @@ class Fuse extends Nanoresource {
|
|||||||
return options.length ? '-o' + options.join(',') : ''
|
return options.length ? '-o' + options.join(',') : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_malloc (size) {
|
||||||
|
const buf = Buffer.alloc(size)
|
||||||
|
this._threads.add(buf)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
_makeHandlerArray () {
|
_makeHandlerArray () {
|
||||||
const self = this
|
const self = this
|
||||||
const handlers = new Array(OpcodesAndDefaults.size)
|
const handlers = new Array(OpcodesAndDefaults.size)
|
||||||
@ -231,10 +238,12 @@ class Fuse extends Nanoresource {
|
|||||||
|
|
||||||
function signal (nativeHandler, err, ...args) {
|
function signal (nativeHandler, err, ...args) {
|
||||||
var arr = [nativeHandler, err, ...args]
|
var arr = [nativeHandler, err, ...args]
|
||||||
|
|
||||||
if (defaults) {
|
if (defaults) {
|
||||||
while (arr.length > 2 && arr[arr.length - 1] === undefined) arr.pop()
|
while (arr.length > 2 && arr[arr.length - 1] === undefined) arr.pop()
|
||||||
if (arr.length === 2) arr = arr.concat(defaults)
|
if (arr.length === 2) arr = arr.concat(defaults)
|
||||||
}
|
}
|
||||||
|
|
||||||
return process.nextTick(nativeSignal, ...arr)
|
return process.nextTick(nativeSignal, ...arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +317,7 @@ class Fuse extends Nanoresource {
|
|||||||
if (parent && parent.dev !== stat.dev) return cb(new Error('Mountpoint in use'))
|
if (parent && parent.dev !== stat.dev) return cb(new Error('Mountpoint in use'))
|
||||||
try {
|
try {
|
||||||
// TODO: asyncify
|
// TODO: asyncify
|
||||||
binding.fuse_native_mount(self.mnt, opts, self._thread, self, self._handlers, implemented)
|
binding.fuse_native_mount(self.mnt, opts, self._thread, self, self._malloc, self._handlers, implemented)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return cb(err)
|
return cb(err)
|
||||||
}
|
}
|
||||||
@ -381,6 +390,7 @@ class Fuse extends Nanoresource {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ops.getattr(path, (err, stat) => {
|
this.ops.getattr(path, (err, stat) => {
|
||||||
if (err) return signal(err, getStatArray())
|
if (err) return signal(err, getStatArray())
|
||||||
return signal(0, getStatArray(stat))
|
return signal(0, getStatArray(stat))
|
||||||
@ -448,13 +458,13 @@ class Fuse extends Nanoresource {
|
|||||||
|
|
||||||
_op_read (signal, path, fd, buf, len, offsetLow, offsetHigh) {
|
_op_read (signal, path, fd, buf, len, offsetLow, offsetHigh) {
|
||||||
this.ops.read(path, fd, buf, len, getDoubleArg(offsetLow, offsetHigh), (err, bytesRead) => {
|
this.ops.read(path, fd, buf, len, getDoubleArg(offsetLow, offsetHigh), (err, bytesRead) => {
|
||||||
return signal(err, bytesRead)
|
return signal(err, bytesRead, buf.buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_op_write (signal, path, fd, buf, len, offsetLow, offsetHigh) {
|
_op_write (signal, path, fd, buf, len, offsetLow, offsetHigh) {
|
||||||
this.ops.write(path, fd, buf, len, getDoubleArg(offsetLow, offsetHigh), (err, bytesWritten) => {
|
this.ops.write(path, fd, buf, len, getDoubleArg(offsetLow, offsetHigh), (err, bytesWritten) => {
|
||||||
return signal(err, bytesWritten)
|
return signal(err, bytesWritten, buf.buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,18 +478,18 @@ class Fuse extends Nanoresource {
|
|||||||
|
|
||||||
_op_setxattr (signal, path, name, value, position, flags) {
|
_op_setxattr (signal, path, name, value, position, flags) {
|
||||||
this.ops.setxattr(path, name, value, position, flags, err => {
|
this.ops.setxattr(path, name, value, position, flags, err => {
|
||||||
return signal(err)
|
return signal(err, value.buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_op_getxattr (signal, path, name, valueBuf, position) {
|
_op_getxattr (signal, path, name, valueBuf, position) {
|
||||||
this.ops.getxattr(path, name, position, (err, value) => {
|
this.ops.getxattr(path, name, position, (err, value) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (!value) return signal(IS_OSX ? -93 : -61)
|
if (!value) return signal(IS_OSX ? -93 : -61, valueBuf.buffer)
|
||||||
value.copy(valueBuf)
|
value.copy(valueBuf)
|
||||||
return signal(value.length)
|
return signal(value.length, valueBuf.buffer)
|
||||||
}
|
}
|
||||||
return signal(err)
|
return signal(err, valueBuf.buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +500,7 @@ class Fuse extends Nanoresource {
|
|||||||
let size = 0
|
let size = 0
|
||||||
for (const name of list) size += Buffer.byteLength(name) + 1
|
for (const name of list) size += Buffer.byteLength(name) + 1
|
||||||
size += 128 // fuse yells if we do not signal room for some mac stuff also
|
size += 128 // fuse yells if we do not signal room for some mac stuff also
|
||||||
return signal(size)
|
return signal(size, listBuf.buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
let ptr = 0
|
let ptr = 0
|
||||||
@ -500,9 +510,9 @@ class Fuse extends Nanoresource {
|
|||||||
listBuf[ptr++] = 0
|
listBuf[ptr++] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return signal(ptr)
|
return signal(ptr, listBuf.buffer)
|
||||||
}
|
}
|
||||||
return signal(err)
|
return signal(err, listBuf.buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user