Skip to content

Commit c27747a

Browse files
Don't make a HEAD request unless there's a local cache file + workaround stale cache locks
1 parent 73c577b commit c27747a

1 file changed

Lines changed: 37 additions & 13 deletions

File tree

requests.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,12 @@ try_init_from_cache(Request *req, char *hostname, char *filePath, INTERNET_SCHEM
236236
DWORD contentLength;
237237
DWORD flags;
238238
bool success;
239-
bool deleteCache;
239+
bool hasCacheEntry;
240+
size_t lockRetryCount;
240241

241242
success = false;
242-
deleteCache = false;
243+
hasCacheEntry = false;
244+
hFile = INVALID_HANDLE_VALUE;
243245
hConn = NULL;
244246
hReq = NULL;
245247
lenlen = sizeof(INTERNET_CACHE_ENTRY_INFOA) + MAX_URL_LENGTH + MAX_PATH;
@@ -259,6 +261,12 @@ try_init_from_cache(Request *req, char *hostname, char *filePath, INTERNET_SCHEM
259261
}
260262
goto cleanup;
261263
}
264+
hasCacheEntry = true;
265+
266+
hFile = CreateFileA(cacheData->lpszLocalFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
267+
if (hFile == INVALID_HANDLE_VALUE) {
268+
goto cleanup;
269+
}
262270

263271
/* Send a HEAD request to validate the cached entry without downloading. */
264272
if (hInternet != NULL) {
@@ -281,11 +289,6 @@ try_init_from_cache(Request *req, char *hostname, char *filePath, INTERNET_SCHEM
281289
}
282290
}
283291

284-
hFile = CreateFileA(cacheData->lpszLocalFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
285-
if (hFile == INVALID_HANDLE_VALUE) {
286-
goto cleanup;
287-
}
288-
289292
/* Compare actual file size on disk against Content-Length to catch truncation. */
290293
if (hReq != NULL) {
291294
DWORD fileSize = GetFileSize(hFile, NULL);
@@ -295,8 +298,6 @@ try_init_from_cache(Request *req, char *hostname, char *filePath, INTERNET_SCHEM
295298
&& fileSize != contentLength) {
296299
logmsg("Cache file truncated for %s: on disk %d, expected %d\n",
297300
req->url, fileSize, contentLength);
298-
CloseHandle(hFile);
299-
deleteCache = true;
300301
goto cleanup;
301302
}
302303
}
@@ -317,10 +318,33 @@ try_init_from_cache(Request *req, char *hostname, char *filePath, INTERNET_SCHEM
317318
InternetCloseHandle(hConn);
318319
}
319320
if (!success) {
320-
UnlockUrlCacheEntryFileA(req->url, 0);
321-
if (deleteCache) {
322-
DeleteUrlCacheEntryA(req->url);
323-
logmsg("Deleted cache entry for %s\n", req->url);
321+
if (hasCacheEntry) {
322+
/*
323+
* The lock count on disk may be polluted, so try to drain a
324+
* reasonable amount of them here. If we still ultimately fail to
325+
* unlock, that's fine; it just means the bad cache entry will be checked
326+
* again on the next request, which will drain the locks even more.
327+
*/
328+
lockRetryCount = 64;
329+
while (UnlockUrlCacheEntryFileA(req->url, 0))
330+
{
331+
lockRetryCount--;
332+
if (lockRetryCount == 0) {
333+
logmsg("Cache entry for %s is hard locked\n", req->url);
334+
break;
335+
}
336+
}
337+
if (DeleteUrlCacheEntryA(req->url)) {
338+
logmsg("Deleted cache entry for %s\n", req->url);
339+
} else {
340+
logmsg("Failed to delete cache entry for %s: %d\n", req->url, GetLastError());
341+
}
342+
}
343+
344+
if (hFile != INVALID_HANDLE_VALUE) {
345+
CloseHandle(hFile);
346+
/* deleting the cache entry doesn't delete the file */
347+
DeleteFileA(cacheData->lpszLocalFileName);
324348
}
325349
}
326350
free(cacheData);

0 commit comments

Comments
 (0)