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/thread.c b/server/thread.c
index e319f51..baaff4c 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -63,21 +63,24 @@
static void dump_thread( struct object *obj, int verbose );
static int thread_signaled( struct object *obj, struct thread *thread );
+extern void thread_poll_event( struct object *obj, int event );
static void destroy_thread( struct object *obj );
static const struct object_ops thread_ops =
{
- sizeof(struct thread),
- dump_thread,
- add_queue,
- remove_queue,
- thread_signaled,
- no_satisfied,
- no_read_fd,
- no_write_fd,
- no_flush,
- no_get_file_info,
- destroy_thread
+ sizeof(struct thread), /* size */
+ dump_thread, /* dump */
+ add_queue, /* add_queue */
+ remove_queue, /* remove_queue */
+ thread_signaled, /* signaled */
+ no_satisfied, /* satisfied */
+ NULL, /* get_poll_events */
+ thread_poll_event, /* poll_event */
+ no_read_fd, /* get_read_fd */
+ no_write_fd, /* get_write_fd */
+ no_flush, /* flush */
+ no_get_file_info, /* get_file_info */
+ destroy_thread /* destroy */
};
static struct thread *first_thread;
@@ -105,9 +108,11 @@
struct thread *thread;
int buf_fd;
- if (!(thread = alloc_object( &thread_ops ))) return NULL;
+ int flags = fcntl( fd, F_GETFL, 0 );
+ fcntl( fd, F_SETFL, flags | O_NONBLOCK );
- thread->client = NULL;
+ if (!(thread = alloc_object( &thread_ops, fd ))) return NULL;
+
thread->unix_pid = 0; /* not known yet */
thread->teb = NULL;
thread->mutex = NULL;
@@ -118,6 +123,7 @@
thread->apc = NULL;
thread->apc_count = 0;
thread->error = 0;
+ thread->pass_fd = -1;
thread->state = RUNNING;
thread->attached = 0;
thread->exit_code = 0x103; /* STILL_ACTIVE */
@@ -142,11 +148,8 @@
add_process_thread( process, thread );
if ((buf_fd = alloc_client_buffer( thread )) == -1) goto error;
- if (!(thread->client = add_client( fd, thread )))
- {
- close( buf_fd );
- goto error;
- }
+
+ set_select_events( &thread->obj, POLLIN ); /* start listening to events */
set_reply_fd( thread, buf_fd ); /* send the fd to the client */
send_reply( thread );
return thread;
@@ -164,6 +167,20 @@
select_loop();
}
+/* handle a client event */
+void thread_poll_event( struct object *obj, int event )
+{
+ struct thread *thread = (struct thread *)obj;
+ assert( obj->ops == &thread_ops );
+
+ if (event & (POLLERR | POLLHUP)) kill_thread( thread, BROKEN_PIPE );
+ else
+ {
+ if (event & POLLOUT) write_request( thread );
+ if (event & POLLIN) read_request( thread );
+ }
+}
+
/* destroy a thread when its refcount is 0 */
static void destroy_thread( struct object *obj )
{
@@ -177,6 +194,7 @@
else first_thread = thread->next;
if (thread->apc) free( thread->apc );
if (thread->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH );
+ if (thread->pass_fd != -1) close( thread->pass_fd );
}
/* dump a thread on stdout for debugging purposes */
@@ -499,21 +517,17 @@
void kill_thread( struct thread *thread, int exit_code )
{
if (thread->state == TERMINATED) return; /* already killed */
- remove_client( thread->client, exit_code ); /* this will call thread_killed */
-}
-
-/* a thread has been killed */
-void thread_killed( struct thread *thread, int exit_code )
-{
thread->state = TERMINATED;
thread->exit_code = exit_code;
- thread->client = NULL;
+ if (current == thread) current = NULL;
+ if (debug_level) trace_kill( thread );
if (thread->wait) end_wait( thread );
debug_exit_thread( thread, exit_code );
abandon_mutexes( thread );
remove_process_thread( thread->process, thread );
wake_up( &thread->obj, 0 );
detach_thread( thread );
+ remove_select_user( &thread->obj );
release_object( thread );
}