Moved poll handling to the generic part of the server objects.
Fixed busy waiting on POLLERR events.
Merged struct client into struct thread.

diff --git a/server/file.c b/server/file.c
index c80ecce..3cc46bd 100644
--- a/server/file.c
+++ b/server/file.c
@@ -32,8 +32,6 @@
 struct file
 {
     struct object       obj;        /* object header */
-    int                 fd;         /* file descriptor */
-    int                 select;     /* select user id */
     struct file        *next;       /* next file in hashing list */
     char               *name;       /* file name */
     unsigned int        access;     /* file access (GENERIC_READ/WRITE) */
@@ -46,9 +44,7 @@
 static struct file *file_hash[NAME_HASH_SIZE];
 
 static void file_dump( struct object *obj, int verbose );
-static int file_add_queue( struct object *obj, struct wait_queue_entry *entry );
-static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
-static int file_signaled( struct object *obj, struct thread *thread );
+static int file_get_poll_events( struct object *obj );
 static int file_get_read_fd( struct object *obj );
 static int file_get_write_fd( struct object *obj );
 static int file_flush( struct object *obj );
@@ -57,17 +53,19 @@
 
 static const struct object_ops file_ops =
 {
-    sizeof(struct file),
-    file_dump,
-    file_add_queue,
-    file_remove_queue,
-    file_signaled,
-    no_satisfied,
-    file_get_read_fd,
-    file_get_write_fd,
-    file_flush,
-    file_get_info,
-    file_destroy
+    sizeof(struct file),          /* size */
+    file_dump,                    /* dump */
+    default_poll_add_queue,       /* add_queue */
+    default_poll_remove_queue,    /* remove_queue */
+    default_poll_signaled,        /* signaled */
+    no_satisfied,                 /* satisfied */
+    file_get_poll_events,         /* get_poll_events */
+    default_poll_event,           /* poll_event */
+    file_get_read_fd,             /* get_read_fd */
+    file_get_write_fd,            /* get_write_fd */
+    file_flush,                   /* flush */
+    file_get_info,                /* get_file_info */
+    file_destroy                  /* destroy */
 };
 
 
@@ -103,23 +101,19 @@
     return 0;
 }
 
+/* create a file from a file descriptor */
+/* if the function fails the fd is closed */
 static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing,
                                         unsigned int attrs )
 {
     struct file *file;
-    if ((file = alloc_object( &file_ops )))
+    if ((file = alloc_object( &file_ops, fd )))
     {
         file->name    = NULL;
         file->next    = NULL;
-        file->fd      = fd;
         file->access  = access;
         file->flags   = attrs;
         file->sharing = sharing;
-        if ((file->select = add_select_user( fd, default_select_event, file )) == -1)
-        {
-            release_object( file );
-            file = NULL;
-        }
     }
     return file;
 }
@@ -171,7 +165,11 @@
         goto error;
     }            
 
-    if (!(file = create_file_for_fd( fd, access, sharing, attrs ))) goto error;
+    if (!(file = create_file_for_fd( fd, access, sharing, attrs )))
+    {
+        free( name );
+        return NULL;
+    }
     file->name = name;
     file->next = file_hash[hash];
     file_hash[hash] = file;
@@ -212,81 +210,41 @@
 /* Create a temp file for anonymous mappings */
 struct file *create_temp_file( int access )
 {
-    struct file *file;
     int fd;
 
     if ((fd = create_anonymous_file()) == -1) return NULL;
-    if (!(file = create_file_for_fd( fd, access, 0, 0 ))) close( fd );
-    return file;
+    return create_file_for_fd( fd, access, 0, 0 );
 }
 
 static void file_dump( struct object *obj, int verbose )
 {
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
-    fprintf( stderr, "File fd=%d flags=%08x name='%s'\n", file->fd, file->flags, file->name );
+    fprintf( stderr, "File fd=%d flags=%08x name='%s'\n", file->obj.fd, file->flags, file->name );
 }
 
-static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
+static int file_get_poll_events( struct object *obj )
 {
     struct file *file = (struct file *)obj;
-    assert( obj->ops == &file_ops );
-    if (!obj->head)  /* first on the queue */
-    {
-        int events = 0;
-        if (file->access & GENERIC_READ) events |= POLLIN;
-        if (file->access & GENERIC_WRITE) events |= POLLOUT;
-        set_select_events( file->select, events );
-    }
-    add_queue( obj, entry );
-    return 1;
-}
-
-static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct file *file = (struct file *)grab_object(obj);
-    assert( obj->ops == &file_ops );
-
-    remove_queue( obj, entry );
-    if (!obj->head)  /* last on the queue is gone */
-        set_select_events( file->select, 0 );
-    release_object( obj );
-}
-
-static int file_signaled( struct object *obj, struct thread *thread )
-{
     int events = 0;
-    struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
-
     if (file->access & GENERIC_READ) events |= POLLIN;
     if (file->access & GENERIC_WRITE) events |= POLLOUT;
-    if (check_select_events( file->fd, events ))
-    {
-        /* stop waiting on select() if we are signaled */
-        set_select_events( file->select, 0 );
-        return 1;
-    }
-    else
-    {
-        /* restart waiting on select() if we are no longer signaled */
-        if (obj->head) set_select_events( file->select, events );
-        return 0;
-    }
+    return events;
 }
 
 static int file_get_read_fd( struct object *obj )
 {
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
-    return dup( file->fd );
+    return dup( file->obj.fd );
 }
 
 static int file_get_write_fd( struct object *obj )
 {
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
-    return dup( file->fd );
+    return dup( file->obj.fd );
 }
 
 static int file_flush( struct object *obj )
@@ -295,7 +253,7 @@
     struct file *file = (struct file *)grab_object(obj);
     assert( obj->ops == &file_ops );
 
-    ret = (fsync( file->fd ) != -1);
+    ret = (fsync( file->obj.fd ) != -1);
     if (!ret) file_set_error();
     release_object( file );
     return ret;
@@ -307,13 +265,13 @@
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
 
-    if (fstat( file->fd, &st ) == -1)
+    if (fstat( file->obj.fd, &st ) == -1)
     {
         file_set_error();
         return 0;
     }
     if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
-        S_ISSOCK(st.st_mode) || isatty(file->fd)) req->type = FILE_TYPE_CHAR;
+        S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) req->type = FILE_TYPE_CHAR;
     else req->type = FILE_TYPE_DISK;
     if (S_ISDIR(st.st_mode)) req->attr = FILE_ATTRIBUTE_DIRECTORY;
     else req->attr = FILE_ATTRIBUTE_ARCHIVE;
@@ -344,7 +302,6 @@
         if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name );
         free( file->name );
     }
-    remove_select_user( file->select );
 }
 
 /* set the last error depending on errno */
@@ -379,7 +336,7 @@
 
 int file_get_mmap_fd( struct file *file )
 {
-    return dup( file->fd );
+    return dup( file->obj.fd );
 }
 
 static int set_file_pointer( int handle, int *low, int *high, int whence )
@@ -396,7 +353,7 @@
 
     if (!(file = get_file_obj( current->process, handle, 0 )))
         return 0;
-    if ((result = lseek( file->fd, *low, whence )) == -1)
+    if ((result = lseek( file->obj.fd, *low, whence )) == -1)
     {
         /* Check for seek before start of file */
         if ((errno == EINVAL) && (whence != SEEK_SET) && (*low < 0))
@@ -418,8 +375,8 @@
 
     if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
         return 0;
-    if (((result = lseek( file->fd, 0, SEEK_CUR )) == -1) ||
-        (ftruncate( file->fd, result ) == -1))
+    if (((result = lseek( file->obj.fd, 0, SEEK_CUR )) == -1) ||
+        (ftruncate( file->obj.fd, result ) == -1))
     {
         file_set_error();
         release_object( file );
@@ -440,13 +397,13 @@
         set_error( ERROR_INVALID_PARAMETER );
         return 0;
     }
-    if (fstat( file->fd, &st ) == -1)
+    if (fstat( file->obj.fd, &st ) == -1)
     {
         file_set_error();
         return 0;
     }
     if (st.st_size >= size_low) return 1;  /* already large enough */
-    if (ftruncate( file->fd, size_low ) != -1) return 1;
+    if (ftruncate( file->obj.fd, size_low ) != -1) return 1;
     file_set_error();
     return 0;
 }
@@ -518,7 +475,6 @@
             req->handle = alloc_handle( current->process, file, req->access, 0 );
             release_object( file );
         }
-        else close( fd );
     }
     else file_set_error();
 }