Added timer on server exit to wait a bit for new clients.
Don't remove the socket until the registry is closed to avoid a race.

diff --git a/server/main.c b/server/main.c
index c6ecfd3..852c93c 100644
--- a/server/main.c
+++ b/server/main.c
@@ -33,7 +33,7 @@
 
 /* command-line options */
 int debug_level = 0;
-int persistent_server = 0;
+int master_socket_timeout = 3;  /* master socket timeout in seconds, default is 3 s */
 
 /* parse-line args */
 /* FIXME: should probably use getopt, and add a (more complete?) help option */
@@ -43,7 +43,7 @@
     fprintf(stderr, "\nusage: %s [options]\n\n", exeName);
     fprintf(stderr, "options:\n");
     fprintf(stderr, "   -d<n>  set debug level to <n>\n");
-    fprintf(stderr, "   -p     make server persistent\n");
+    fprintf(stderr, "   -p[n]  make server persistent, optionally for n seconds\n");
     fprintf(stderr, "   -h     display this help message\n");
     fprintf(stderr, "\n");
 }
@@ -66,7 +66,8 @@
                 exit(0);
                 break;
             case 'p':
-                persistent_server = 1;
+                if (isdigit(argv[i][2])) master_socket_timeout = atoi( argv[i] + 2 );
+                else master_socket_timeout = -1;
                 break;
             default:
                 fprintf( stderr, "Unknown option '%s'\n", argv[i] );
diff --git a/server/object.h b/server/object.h
index 378a1ae..6ccbeaf 100644
--- a/server/object.h
+++ b/server/object.h
@@ -198,7 +198,7 @@
 
   /* command-line options */
 extern int debug_level;
-extern int persistent_server;
+extern int master_socket_timeout;
 
   /* server start time used for GetTickCount() */
 extern unsigned int server_start_ticks;
diff --git a/server/process.c b/server/process.c
index 8de97b0..2162be2 100644
--- a/server/process.c
+++ b/server/process.c
@@ -497,7 +497,7 @@
         /* last process died, close global handles */
         close_global_handles();
         /* this will cause the select loop to terminate */
-        if (!persistent_server) close_master_socket();
+        close_master_socket();
     }
 }
 
diff --git a/server/request.c b/server/request.c
index 623520d..7ed598f 100644
--- a/server/request.c
+++ b/server/request.c
@@ -60,12 +60,12 @@
 
 struct master_socket
 {
-    struct object       obj;         /* object header */
+    struct object        obj;         /* object header */
+    struct timeout_user *timeout;    /* timeout on last process exit */
 };
 
 static void master_socket_dump( struct object *obj, int verbose );
 static void master_socket_poll_event( struct object *obj, int event );
-static void master_socket_destroy( struct object *obj );
 
 static const struct object_ops master_socket_ops =
 {
@@ -81,7 +81,7 @@
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
     NULL,                          /* queue_async */
-    master_socket_destroy          /* destroy */
+    no_destroy                     /* destroy */
 };
 
 
@@ -447,6 +447,11 @@
         int len = sizeof(dummy);
         int client = accept( master_socket->obj.fd, (struct sockaddr *) &dummy, &len );
         if (client == -1) return;
+        if (sock->timeout)
+        {
+            remove_timeout_user( sock->timeout );
+            sock->timeout = NULL;
+        }
         fcntl( client, F_SETFL, O_NONBLOCK );
         create_process( client );
     }
@@ -459,11 +464,6 @@
     if (!do_it_once++) unlink( SOCKETNAME );
 }
 
-static void master_socket_destroy( struct object *obj )
-{
-    socket_cleanup();
-}
-
 /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */
 const char *get_config_dir(void)
 {
@@ -557,6 +557,7 @@
 
     if (!(master_socket = alloc_object( &master_socket_ops, fd )))
         fatal_error( "out of memory\n" );
+    master_socket->timeout = NULL;
     set_select_events( &master_socket->obj, POLLIN );
 
     /* setup msghdr structure constant fields */
@@ -581,14 +582,30 @@
     }
 }
 
-/* close the master socket and stop waiting for new clients */
-void close_master_socket(void)
+/* master socket timer expiration handler */
+static void close_socket_timeout( void *arg )
 {
     /* if a new client is waiting, we keep on running */
     if (!check_select_events( master_socket->obj.fd, POLLIN ))
         release_object( master_socket );
 }
 
+/* close the master socket and stop waiting for new clients */
+void close_master_socket(void)
+{
+    struct timeval when;
+
+    if (master_socket_timeout == -1) return;  /* just keep running forever */
+
+    if (master_socket_timeout)
+    {
+        gettimeofday( &when, 0 );
+        add_timeout( &when, master_socket_timeout * 1000 );
+        master_socket->timeout = add_timeout_user( &when, close_socket_timeout, NULL );
+    }
+    else close_socket_timeout( NULL );  /* close it right away */
+}
+
 /* lock/unlock the master socket to stop accepting new clients */
 void lock_master_socket( int locked )
 {
diff --git a/server/select.c b/server/select.c
index 065c456..24cbdb6 100644
--- a/server/select.c
+++ b/server/select.c
@@ -274,6 +274,7 @@
                     break;
                 }
             }
+            if (!active_users) break;  /* last user removed by a timeout */
         }
 
         sigprocmask( SIG_UNBLOCK, &sigset, NULL );