-
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!
Metadata
Metadata
Assignees
Labels
No labels