The flock() was taken on the merged file itself. Its lock was released
before the chunks were deleted and before add_uploaded_file() renamed the
file: a request which got the lock just after could truncate the merged
file while it was being moved, or delete it.
The merge now runs under a pwg_unique_exec token per series, kept until
the end of the request (released by a shutdown function, which also runs
after a fatal error such as max_execution_time exceeded). The series is
checked again once the token is obtained, so a request arriving after a
completed merge gives up without touching anything. The token lives in the
database: it also works with several web servers sharing the buffer
directory. Tokens left by a killed request are removed by the housekeeping.
Related to #2583
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vty6FTwtZ3ezEncagFo2FQ