# HG changeset patch # User Tero Marttila # Date 1226966812 -7200 # Node ID 40a3b13ffc9dac8e240342ad5a488514b2bac7ef # Parent 6abda2fa457918e65d165f3e84c8597f015fab95 defer fuse_reply_err using event_base_once, interrupt happens without deadlock now diff -r 6abda2fa4579 -r 40a3b13ffc9d src/dbfs/dbfs.h --- a/src/dbfs/dbfs.h Tue Nov 18 01:55:13 2008 +0200 +++ b/src/dbfs/dbfs.h Tue Nov 18 02:06:52 2008 +0200 @@ -81,6 +81,8 @@ /* * Useable as a callback to fuse_req_interrupt_func, will abort the given query and err the req. + * + * Due to a locking bug in libfuse 2.7.4, this will actually delay the fuse_req_err until the next event-loop iteration. */ void dbfs_interrupt_query (struct fuse_req *req, void *query_ptr); diff -r 6abda2fa4579 -r 40a3b13ffc9d src/dbfs/interrupt.c --- a/src/dbfs/interrupt.c Tue Nov 18 01:55:13 2008 +0200 +++ b/src/dbfs/interrupt.c Tue Nov 18 02:06:52 2008 +0200 @@ -1,16 +1,32 @@ #include "dbfs.h" +void _dbfs_interrupt_reply (evutil_socket_t _unused1, short _unused2, void *req_ptr) { + struct fuse_req *req = req_ptr; + err_t err; + + // error the req + if ((err = -fuse_reply_err(req, EINTR))) + EWARNING(err, "fuse_reply_err"); +} + void dbfs_interrupt_query (struct fuse_req *req, void *query_ptr) { + struct dbfs *ctx = fuse_req_userdata(req); struct evsql_query *query = query_ptr; + struct timeval tv; err_t err; - // abort + // abort query evsql_query_abort(NULL, query); - - // error the req - if ((err = -fuse_reply_err(req, EINTR))) - PWARNING("fuse_reply_err", err); + + /* + * Due to a locking bug in libfuse (at least 2.7.4), we can't call fuse_reply_err from the interrupt function, so we must + * schedule after this function returns. + */ + tv.tv_sec = 0; + tv.tv_usec = 0; + if (event_base_once(ctx->ev_base, -1, EV_TIMEOUT, _dbfs_interrupt_reply, req, &tv)) + PWARNING("event_base_once failed, dropping req reply: %p", req); } void _dbfs_interrupt_ctx (struct fuse_req *req, void *ctx_ptr) {