mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 22:00:13 +01:00
util/disk_cache: don't deadlock on premature EOF
If we get EOF earlier than expected, the current read loops will
deadlock. This may easily happen if the disk cache gets corrupted.
Fix it by using a helper function that handles EOF.
Steps to reproduce (on a build with asserts disabled):
$ glxgears
$ find ~/.cache/mesa/ -type f -exec truncate -s 0 '{}' \;
$ glxgears # deadlock
Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
This commit is contained in:
parent
7414326164
commit
b9e92334f7
1 changed files with 26 additions and 17 deletions
|
|
@ -641,6 +641,21 @@ disk_cache_remove(struct disk_cache *cache, const cache_key key)
|
|||
p_atomic_add(cache->size, - (uint64_t)sb.st_size);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
read_all(int fd, void *buf, size_t count)
|
||||
{
|
||||
char *in = buf;
|
||||
ssize_t read_ret;
|
||||
size_t done;
|
||||
|
||||
for (done = 0; done < count; done += read_ret) {
|
||||
read_ret = read(fd, in + done, count - done);
|
||||
if (read_ret == -1 || read_ret == 0)
|
||||
return -1;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
write_all(int fd, const void *buf, size_t count)
|
||||
{
|
||||
|
|
@ -938,7 +953,7 @@ inflate_cache_data(uint8_t *in_data, size_t in_data_size,
|
|||
void *
|
||||
disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
|
||||
{
|
||||
int fd = -1, ret, len;
|
||||
int fd = -1, ret;
|
||||
struct stat sb;
|
||||
char *filename = NULL;
|
||||
uint8_t *data = NULL;
|
||||
|
|
@ -969,13 +984,11 @@ disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
|
|||
goto fail;
|
||||
|
||||
assert(sb.st_size > ck_size);
|
||||
for (len = 0; len < ck_size; len += ret) {
|
||||
ret = read(fd, ((uint8_t *) file_header) + len, ck_size - len);
|
||||
ret = read_all(fd, file_header, ck_size);
|
||||
if (ret == -1) {
|
||||
free(file_header);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
assert(memcmp(cache->driver_keys_blob, file_header, ck_size) == 0);
|
||||
|
||||
|
|
@ -992,19 +1005,15 @@ disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
|
|||
/* Load the CRC that was created when the file was written. */
|
||||
struct cache_entry_file_data cf_data;
|
||||
size_t cf_data_size = sizeof(cf_data);
|
||||
for (len = 0; len < cf_data_size; len += ret) {
|
||||
ret = read(fd, ((uint8_t *) &cf_data) + len, cf_data_size - len);
|
||||
ret = read_all(fd, &cf_data, cf_data_size);
|
||||
if (ret == -1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Load the actual cache data. */
|
||||
size_t cache_data_size = sb.st_size - cf_data_size - ck_size;
|
||||
for (len = 0; len < cache_data_size; len += ret) {
|
||||
ret = read(fd, data + len, cache_data_size - len);
|
||||
ret = read_all(fd, data, cache_data_size);
|
||||
if (ret == -1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Uncompress the cache data */
|
||||
uncompressed_data = malloc(cf_data.uncompressed_size);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue