The problem
file_unmanaged_save_data() calls file_unmanaged_move().
file_unmanaged_move() calls file_unmanaged_copy(), which calls cp.
cp is not atomic, mv is (per http://stackoverflow.com/questions/11231198/should-my-script-use-cp-or-m... and others).
This can and does lead to race conditions where one process starts writing a file, and another starts reading it before it's finished, and gets an incomplete/empty file.
At least three contrib projects have their own versions of file_unmanaged_save_data(), dating back to 2012 or earlier, but I couldn't find a core issue:
boost: http://api.drupal.psu.edu/api/drupal/modules!contrib!boost!boost.module/...
advagg: http://www.rit.edu/drupal/api/drupal/sites!all!modules!advagg!advagg.mis...
agrcache: #2628918: Address deployment race conditions
Proposed solution
1. fix file_unmanaged_save_data() to use rename() instead of copy()
If that's too much of a behaviour change, we could add a new function/method, but don't really see why it'd be a problem to just fix it.
Remaining tasks
Comment | File | Size | Author |
---|---|---|---|
#2 | 2688389-1.patch | 4.32 KB | Anonymous (not verified) |
Comments
Comment #2
Anonymous (not verified) CreditAttribution: Anonymous commentedhow about this.
Comment #4
catchJust found #2688389: file_unmanaged_save_data()/file_unmanaged_move() are not atomic, marking this as duplicate of that, let's continue over there.
Comment #5
mcdruidAFAICS this should be marked as a duplicate of #1377740: file_unmanaged_move() should issue rename() where possible instead of copy() & unlink() rather than of itself :)