-
Notifications
You must be signed in to change notification settings - Fork 11
Open
Description
Describe the Bug
A mutex leak in fs_write_finished() causes file-specific deadlock when the server returns retriable errors. The function acquires a file mutex but returns without releasing it when encountering error codes 1007 or 5003, bypassing the normal unlock path.
Location: pfs.c (lines 2689-2722)
static void fs_write_finished(psync_socket *api, void *_wt)
{
// ... error handling ...
pthread_mutex_lock(&of->mutex); // File mutex acquired (line 2689)
if (!res) {
debug(D_WARNING, "failed! setting error to %d of file %s", NOT_CONNECTED_ERR, of->file->name);
of->error = NOT_CONNECTED_ERR;
if (of->waitcmd)
pthread_cond_broadcast(&of->cond);
goto decref; // Goes to unlock
}
sub = find_res(res, "result");
if (!sub || sub->type != PARAM_NUM) {
debug(D_BUG, "EIO");
of->error = -EIO;
if (of->waitcmd)
pthread_cond_broadcast(&of->cond);
}
else if (sub->num != 0) {
if ((sub->num == 1007 || sub->num == 5003) && wt->tries < fs_settings.retrycnt) {
reset_conn_id(of);
return reschedule_write(wt); // BUG: Returns without unlock! (line 2707)
}
debug(D_ERROR, "error %u", (int unsigned)sub->num);
of->error = convert_error(sub->num);
if (of->waitcmd)
pthread_cond_broadcast(&of->cond);
}
decref: // This label is bypassed on line 2707
dec_openfile_refcnt_locked(of);
pthread_mutex_unlock(&of->mutex); // Never reached on error 1007/5003 (line 2722)
free(_wt);
}Impact:
- File's
of->mutexremains permanently locked after encountering retriable errors - All subsequent operations on that specific file (read, write, close) deadlock permanently
- User cannot access or close the affected file → Denial of Service for that file
- Multiple files can be affected if error occurs repeatedly
Execution Flow:
Thread 1 (write operation on file A):
→ pthread_mutex_lock(&of->mutex) // Lock file A's mutex
→ Server returns error 1007 or 5003 // Retriable error
→ if ((sub->num == 1007 || sub->num == 5003) && ...)
→ reset_conn_id(of)
→ return reschedule_write(wt) // EXIT - bypasses decref label
→ of->mutex (file A) remains locked forever
Thread 2 (any operation on file A):
→ Attempt to read/write/close file A
→ pthread_mutex_lock(&of->mutex) // BLOCKS permanently
→ File A becomes permanently inaccessible
Other files:
→ Operations on other files continue normally
→ But if errors 1007/5003 occur, those files also become locked
This occurs when the pCloud server returns error codes:
- 1007: Typically connection/retry errors
- 5003: Typically service unavailable errors
And the retry count has not been exhausted. The function attempts to reschedule the write but forgets to unlock the file mutex.
I would appreciate it if you could review and confirm this potential issue. Thank you for your time and for maintaining this project!
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels