mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix(uploads): bound the paste-image workspace probe (#516)
The paste-image route wrote under session.workingDir via ensureUploadDir with no bounded probe, so an upload onto a stalled network mount held one of libuv's few threadpool workers until the mount answered. Probe the workspace with probePathKind past the stall cap before the first disk touch and refuse an unknown mount through describeUnknownPath, the way POST /api/sessions already does.
This commit is contained in:
1 parent
aa3730aace
commit
3e75e7509f
5 files changed
+104
-9
No files matched your search
@@ -374,7 +374,9 @@ export function imageMagicMatchesExt(data: Buffer, ext: string): boolean {
|
||||
* touched, and a file already there is theirs and stays as it is.
|
||||
*/
|
||||
async function ensureUploadDir(workingDir: string): Promise<string | null> {
|
||||
// workingDir is guaranteed to exist (live session).
|
||||
// workingDir exists (live session) and the caller bounded-probed its mount, so
|
||||
// the lstat/mkdir below normally start on a reachable path; a mount that dies
|
||||
// after that probe is the same residual race POST /api/sessions accepts.
|
||||
const uploadDir = join(workingDir, UPLOADS_DIR);
|
||||
try {
|
||||
const dirStat = await fs.lstat(uploadDir);
|
||||
@@ -5258,6 +5260,20 @@ export function registerSessionRoutes(
|
||||
);
|
||||
}
|
||||
|
||||
// The upload is written under session.workingDir (ensureUploadDir below), and
|
||||
// a live session's workspace can sit on a network mount that stopped answering.
|
||||
// Probe it bounded before the first disk touch, as #516 requires for a path the
|
||||
// user named, so one dead mount cannot freeze a libuv threadpool worker per
|
||||
// upload. Only "unknown" (the mount is not answering) is refused here, the way
|
||||
// the create route does; absent / not-a-directory keep ensureUploadDir's own
|
||||
// errors, since a live session's workspace should be neither.
|
||||
if ((await probePathKind(session.workingDir, { pastCap: true })) === 'unknown') {
|
||||
return createErrorResponse(
|
||||
ApiErrorCode.OPERATION_FAILED,
|
||||
describeUnknownPath('Workspace', session.workingDir, { pastCap: true })
|
||||
);
|
||||
}
|
||||
|
||||
if (!req.isMultipart()) {
|
||||
reply.code(400);
|
||||
return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Expected multipart/form-data');
|
||||
|
||||
Reference in new issue
Block a user