Fix a race condtition in the server startup
Francois Gouget
fgouget at codeweavers.com
Sat Feb 26 17:43:34 CST 2005
There is a race condition in the server startup code which arises if two
Wine processes are started simultaneously and the server directory (i.e.
/tmp/.wine-uid/server-XXX-XXXX) does not exist yet. The symptom is that
the server prints the following message:
wineserver: mkdir /tmp/.wine-2939/server-302-bbeb6 : File exists
This is because, before the wineservers can create the wineserver lock,
and thus serialize their operations, they must create the server
directory. This goes through this code which has a race condition:
if (lstat( name, st ) == -1)
{
if (errno != ENOENT) fatal_perror( "lstat %s", name );
if (mkdir( name, 0700 ) == -1) fatal_perror( "mkdir %s", name );
...
}
The race condition is:
wineserver 1 wineserver 2
------------ ------------
lstat() == -1
errno != ENOENT
lstat() == -1
errno != ENOENT
mkdir()==0
mkdir()==-1
The mkdir() error causes wineserver 1 to exit with an error and the
corresponding Wine process to fail (it cannot even fall back to
wineserver 2 since it may not be fully started yet).
I propose the following fix:
if (lstat( name, st ) == -1)
{
if (errno != ENOENT) fatal_perror( "lstat %s", name );
if (mkdir( name, 0700 ) == -1 && errno != EEXIST) fatal_perror(
"mkdir %s", name );
Using the existing directory is ok because we then check its ownership,
permissions, etc. (which we have to do anyway in case it already existed).
Changelog:
* server/request.c
Francois Gouget <fgouget at codeweavers.com>
Fix a race condition in create_dir().
--
Francois Gouget
fgouget at codeweavers.com
-------------- next part --------------
Index: server/request.c
===================================================================
RCS file: /var/cvs/wine/server/request.c,v
retrieving revision 1.83
diff -u -p -r1.83 request.c
--- server/request.c 3 Feb 2005 10:46:15 -0000 1.83
+++ server/request.c 26 Feb 2005 23:30:12 -0000
@@ -509,7 +509,7 @@ static void create_dir( const char *name
if (lstat( name, st ) == -1)
{
if (errno != ENOENT) fatal_perror( "lstat %s", name );
- if (mkdir( name, 0700 ) == -1) fatal_perror( "mkdir %s", name );
+ if (mkdir( name, 0700 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", name );
if (lstat( name, st ) == -1) fatal_perror( "lstat %s", name );
}
if (!S_ISDIR(st->st_mode)) fatal_error( "%s is not a directory\n", name );
More information about the wine-patches
mailing list