aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Stone <a@stne.dev>2021-02-25 04:13:30 -0800
committerGitHub <noreply@github.com>2021-02-25 12:13:30 +0000
commit6c1b92df814622cfca793657e0060335b39bd61e (patch)
treebf783c75ee69de28cbc379ccfbcb792c0041b8bb
parentd18869a30746406ab26da1561afd197b68cbe878 (diff)
downloadsshfs-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.c26
1 files changed, 10 insertions, 16 deletions
diff --git a/sshfs.c b/sshfs.c
index 0a40950..32130e1 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -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;
}