diff options
author | 2013-02-05 13:36:06 +0100 | |
---|---|---|
committer | 2013-02-05 13:36:06 +0100 | |
commit | eca08beaf5a7b4121da27c2a927a6ecbb08a74bf (patch) | |
tree | 5aee2b83578d489d3d7ac8d2e759ff5b1ba43894 /lib/fuse.c | |
parent | 95e1a99472b11560d98046fc2427788be0c14412 (diff) |
libfuse: fix fuse_get_context() in non fuse threads
fuse_interrupted(), fuse_get_context(), etc... crashed in non-fuse threads.
Instead return false, NULL or error depending on the function.
Reported by Michael Berlin
Diffstat (limited to 'lib/fuse.c')
-rw-r--r-- | lib/fuse.c | 48 |
1 files changed, 30 insertions, 18 deletions
@@ -2368,9 +2368,12 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid, static struct fuse_context_i *fuse_get_context_internal(void) { - struct fuse_context_i *c; + return (struct fuse_context_i *) pthread_getspecific(fuse_context_key); +} - c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key); +static struct fuse_context_i *fuse_create_context(struct fuse *f) +{ + struct fuse_context_i *c = fuse_get_context_internal(); if (c == NULL) { c = (struct fuse_context_i *) calloc(1, sizeof(struct fuse_context_i)); @@ -2383,7 +2386,11 @@ static struct fuse_context_i *fuse_get_context_internal(void) abort(); } pthread_setspecific(fuse_context_key, c); + } else { + memset(c, 0, sizeof(*c)); } + c->ctx.fuse = f; + return c; } @@ -2423,10 +2430,9 @@ static void fuse_delete_context_key(void) static struct fuse *req_fuse_prepare(fuse_req_t req) { - struct fuse_context_i *c = fuse_get_context_internal(); + struct fuse_context_i *c = fuse_create_context(req_fuse(req)); const struct fuse_ctx *ctx = fuse_req_ctx(req); c->req = req; - c->ctx.fuse = req_fuse(req); c->ctx.uid = ctx->uid; c->ctx.gid = ctx->gid; c->ctx.pid = ctx->pid; @@ -2470,10 +2476,8 @@ void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) static void fuse_lib_init(void *data, struct fuse_conn_info *conn) { struct fuse *f = (struct fuse *) data; - struct fuse_context_i *c = fuse_get_context_internal(); - memset(c, 0, sizeof(*c)); - c->ctx.fuse = f; + fuse_create_context(f); conn->want |= FUSE_CAP_EXPORT_SUPPORT; fuse_fs_init(f->fs, conn); } @@ -2491,10 +2495,8 @@ void fuse_fs_destroy(struct fuse_fs *fs) static void fuse_lib_destroy(void *data) { struct fuse *f = (struct fuse *) data; - struct fuse_context_i *c = fuse_get_context_internal(); - memset(c, 0, sizeof(*c)); - c->ctx.fuse = f; + fuse_create_context(f); fuse_fs_destroy(f->fs); f->fs = NULL; } @@ -4189,18 +4191,31 @@ void fuse_exit(struct fuse *f) struct fuse_context *fuse_get_context(void) { - return &fuse_get_context_internal()->ctx; + struct fuse_context_i *c = fuse_get_context_internal(); + + if (c) + return &c->ctx; + else + return NULL; } int fuse_getgroups(int size, gid_t list[]) { - fuse_req_t req = fuse_get_context_internal()->req; - return fuse_req_getgroups(req, size, list); + struct fuse_context_i *c = fuse_get_context_internal(); + if (!c) + return -EINVAL; + + return fuse_req_getgroups(c->req, size, list); } int fuse_interrupted(void) { - return fuse_req_interrupted(fuse_get_context_internal()->req); + struct fuse_context_i *c = fuse_get_context_internal(); + + if (c) + return fuse_req_interrupted(c->req); + else + return 0; } void fuse_set_getcontext_func(struct fuse_context *(*func)(void)) @@ -4589,10 +4604,7 @@ void fuse_destroy(struct fuse *f) fuse_restore_intr_signal(f->conf.intr_signal); if (f->fs) { - struct fuse_context_i *c = fuse_get_context_internal(); - - memset(c, 0, sizeof(*c)); - c->ctx.fuse = f; + fuse_create_context(f); for (i = 0; i < f->id_table.size; i++) { struct node *node; |