diff options
author | Andrew Stone <a@stne.dev> | 2021-02-25 04:13:30 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-25 12:13:30 +0000 |
commit | 6c1b92df814622cfca793657e0060335b39bd61e (patch) | |
tree | bf783c75ee69de28cbc379ccfbcb792c0041b8bb | |
parent | d18869a30746406ab26da1561afd197b68cbe878 (diff) | |
download | sshfs-6c1b92df814622cfca793657e0060335b39bd61e.tar sshfs-6c1b92df814622cfca793657e0060335b39bd61e.tar.gz sshfs-6c1b92df814622cfca793657e0060335b39bd61e.tar.bz2 sshfs-6c1b92df814622cfca793657e0060335b39bd61e.zip |
Fix deadlock in conn cleanup (#244)
Calling through to request_free() from clean_req() causes deadlock since
sshfs.lock is already held by the caller of clean_req().
-rw-r--r-- | sshfs.c | 26 |
1 files changed, 10 insertions, 16 deletions
@@ -1401,9 +1401,11 @@ static int sftp_read(struct conn *conn, uint8_t *type, struct buffer *buf) static void request_free(struct request *req) { - pthread_mutex_lock(&sshfs.lock); + if (req->end_func) + req->end_func(req); + req->conn->req_count--; - pthread_mutex_unlock(&sshfs.lock); + buf_free(&req->reply); sem_destroy(&req->ready); g_free(req); @@ -1449,11 +1451,9 @@ static int clean_req(void *key, struct request *req, gpointer user_data) req->error = -EIO; if (req->want_reply) sem_post(&req->ready); - else { - if (req->end_func) - req->end_func(req); + else request_free(req); - } + return TRUE; } @@ -1515,12 +1515,9 @@ static int process_one_request(struct conn *conn) if (req->want_reply) sem_post(&req->ready); else { - if (req->end_func) { - pthread_mutex_lock(&sshfs.lock); - req->end_func(req); - pthread_mutex_unlock(&sshfs.lock); - } + pthread_mutex_lock(&sshfs.lock); request_free(req); + pthread_mutex_unlock(&sshfs.lock); } } else buf_free(&buf); @@ -1970,12 +1967,9 @@ static int sftp_request_wait(struct request *req, uint8_t type, } out: - if (req->end_func) { - pthread_mutex_lock(&sshfs.lock); - req->end_func(req); - pthread_mutex_unlock(&sshfs.lock); - } + pthread_mutex_lock(&sshfs.lock); request_free(req); + pthread_mutex_unlock(&sshfs.lock); return err; } |