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