Fixed possible race-condition in FD cache patches.

This commit is contained in:
Sebastian Lackner
2014-05-31 18:38:40 +02:00
parent 24d682fd91
commit 1800d1f853
3 changed files with 21 additions and 28 deletions

View File

@@ -1,14 +1,14 @@
From a28102527d80bd4c499bcf21d871565665f5606d Mon Sep 17 00:00:00 2001
From b02cb296f5b0c7b6e358e882e820edf079f6e81b Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 31 May 2014 03:21:39 +0200
Subject: ntdll: Use lockfree implementation for get_cached_fd.
---
dlls/ntdll/server.c | 57 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 40 insertions(+), 17 deletions(-)
1 file changed, 41 insertions(+), 16 deletions(-)
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index f3c6b38..6a6082a 100644
index f3c6b38..749eda5 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -787,17 +787,27 @@ static int receive_fd( obj_handle_t *handle )
@@ -42,15 +42,16 @@ index f3c6b38..6a6082a 100644
static struct fd_cache_entry *fd_cache[FD_CACHE_ENTRIES];
static struct fd_cache_entry fd_cache_initial_block[FD_CACHE_BLOCK_SIZE];
@@ -818,6 +828,7 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
@@ -818,7 +828,7 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
unsigned int access, unsigned int options )
{
unsigned int entry, idx = handle_to_index( handle, &entry );
- int prev_fd;
+ union fd_cache_entry_attrs attrs;
int prev_fd;
if (entry >= FD_CACHE_ENTRIES)
@@ -837,11 +848,16 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
{
@@ -837,33 +847,44 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
fd_cache[entry] = ptr;
}
}
@@ -64,14 +65,14 @@ index f3c6b38..6a6082a 100644
- fd_cache[entry][idx].type = type;
- fd_cache[entry][idx].access = access;
- fd_cache[entry][idx].options = options;
+ prev_fd = interlocked_xchg( &fd_cache[entry][idx].fd, 0 ) - 1;
- if (prev_fd != -1) close( prev_fd );
+ assert( !fd_cache[entry][idx].fd );
+ interlocked_xchg_add( &fd_cache_epoch, 1 );
+ fd_cache[entry][idx].attrs.value = attrs.value;
+ fd_cache[entry][idx].fd = fd + 1;
if (prev_fd != -1) close( prev_fd );
return TRUE;
}
@@ -849,22 +865,30 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
/***********************************************************************
* get_cached_fd
@@ -105,31 +106,23 @@ index f3c6b38..6a6082a 100644
+ if (access) *access = attrs.s.access;
+ if (options) *options = attrs.s.options;
}
+
return fd;
}
@@ -901,11 +925,10 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
@@ -901,6 +922,9 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
*needs_close = 0;
wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA;
- server_enter_uninterrupted_section( &fd_cache_section, &sigset );
-
fd = get_cached_fd( handle, type, &access, options );
if (fd != -1) goto done;
+ fd = get_cached_fd( handle, type, &access, options );
+ if (fd != -1) goto done_unlocked;
+
server_enter_uninterrupted_section( &fd_cache_section, &sigset );
+ server_enter_uninterrupted_section( &fd_cache_section, &sigset );
SERVER_START_REQ( get_handle_fd )
{
req->handle = wine_server_obj_handle( handle );
@@ -925,9 +948,9 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
}
}
SERVER_END_REQ;
+ server_leave_uninterrupted_section( &fd_cache_section, &sigset );
fd = get_cached_fd( handle, type, &access, options );
@@ -928,6 +952,7 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
done:
- server_leave_uninterrupted_section( &fd_cache_section, &sigset );
server_leave_uninterrupted_section( &fd_cache_section, &sigset );
+done_unlocked:
if (!ret && ((access & wanted_access) != wanted_access))
{
ret = STATUS_ACCESS_DENIED;

View File

@@ -1,3 +1,3 @@
Revision: 1
Revision: 2
Author: Sebastian Lackner
Title: Use lockfree implementation for get_cached_fd.