Redesign of the server communication protocol to allow arbitrary sized
data to be exchanged.
Split request and reply structures to make backwards compatibility
easier.
Moved many console functions to dlls/kernel, added code page support,
changed a few requests to behave properly with the new protocol.
diff --git a/server/thread.c b/server/thread.c
index 8382229..c568750 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -14,9 +14,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
@@ -104,7 +101,10 @@
thread->user_apc.head = NULL;
thread->user_apc.tail = NULL;
thread->error = 0;
- thread->request_fd = NULL;
+ thread->req_data = NULL;
+ thread->req_toread = 0;
+ thread->reply_data = NULL;
+ thread->reply_towrite = 0;
thread->reply_fd = -1;
thread->wait_fd = -1;
thread->state = RUNNING;
@@ -115,7 +115,6 @@
thread->priority = THREAD_PRIORITY_NORMAL;
thread->affinity = 1;
thread->suspend = 0;
- thread->buffer = (void *)-1;
for (i = 0; i < MAX_INFLIGHT_FDS; i++)
thread->inflight[i].server = thread->inflight[i].client = -1;
@@ -131,6 +130,7 @@
init_thread_structure( thread );
thread->process = (struct process *)grab_object( process );
+ thread->request_fd = fd;
if (!current) current = thread;
if (!booting_thread) /* first thread ever */
@@ -142,7 +142,6 @@
if ((thread->next = first_thread) != NULL) thread->next->prev = thread;
first_thread = thread;
- fcntl( fd, F_SETFL, O_NONBLOCK );
set_select_events( &thread->obj, POLLIN ); /* start listening to events */
add_process_thread( thread->process, thread );
return thread;
@@ -156,6 +155,7 @@
if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
else if (event & POLLIN) read_request( thread );
+ else if (event & POLLOUT) write_reply( thread );
}
/* cleanup everything that is no longer needed by a dead thread */
@@ -166,10 +166,11 @@
struct thread_apc *apc;
while ((apc = thread_dequeue_apc( thread, 0 ))) free( apc );
- if (thread->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH );
+ if (thread->req_data) free( thread->req_data );
+ if (thread->reply_data) free( thread->reply_data );
+ if (thread->request_fd != -1) close( thread->request_fd );
if (thread->reply_fd != -1) close( thread->reply_fd );
if (thread->wait_fd != -1) close( thread->wait_fd );
- if (thread->request_fd) release_object( thread->request_fd );
if (thread->queue)
{
if (thread->process->queue == thread->queue)
@@ -189,10 +190,11 @@
thread->inflight[i].client = thread->inflight[i].server = -1;
}
}
- thread->buffer = (void *)-1;
+ thread->req_data = NULL;
+ thread->reply_data = NULL;
+ thread->request_fd = -1;
thread->reply_fd = -1;
thread->wait_fd = -1;
- thread->request_fd = NULL;
}
/* destroy a thread when its refcount is 0 */
@@ -255,7 +257,7 @@
/* set all information about a thread */
static void set_thread_info( struct thread *thread,
- struct set_thread_info_request *req )
+ const struct set_thread_info_request *req )
{
if (req->mask & SET_THREAD_INFO_PRIORITY)
thread->priority = req->priority;
@@ -467,7 +469,8 @@
}
/* select on a list of handles */
-static void select_on( int count, void *cookie, handle_t *handles, int flags, int sec, int usec )
+static void select_on( int count, void *cookie, const handle_t *handles,
+ int flags, int sec, int usec )
{
int ret, i;
struct object *objects[MAXIMUM_WAIT_OBJECTS];
@@ -700,6 +703,8 @@
remove_process_thread( thread->process, thread );
wake_up( &thread->obj, 0 );
detach_thread( thread, violent_death ? SIGTERM : 0 );
+ if (thread->request_fd == thread->obj.fd) thread->request_fd = -1;
+ if (thread->reply_fd == thread->obj.fd) thread->reply_fd = -1;
remove_select_user( &thread->obj );
cleanup_thread( thread );
release_object( thread );
@@ -746,8 +751,9 @@
struct thread *thread;
int request_fd = thread_get_inflight_fd( current, req->request_fd );
- if (request_fd == -1)
+ if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
{
+ if (request_fd != -1) close( request_fd );
set_error( STATUS_INVALID_HANDLE );
return;
}
@@ -755,9 +761,9 @@
if ((thread = create_thread( request_fd, current->process )))
{
if (req->suspend) thread->suspend++;
- req->tid = thread;
- if ((req->handle = alloc_handle( current->process, thread,
- THREAD_ALL_ACCESS, req->inherit )))
+ reply->tid = thread;
+ if ((reply->handle = alloc_handle( current->process, thread,
+ THREAD_ALL_ACCESS, req->inherit )))
{
/* thread object will be released when the thread gets killed */
return;
@@ -778,7 +784,7 @@
fatal_protocol_error( current, "init_thread: already running\n" );
goto error;
}
- if (reply_fd == -1)
+ if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1)
{
fatal_protocol_error( current, "bad reply fd\n" );
goto error;
@@ -798,10 +804,10 @@
if (current->process->running_threads > 1)
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
- req->pid = get_process_id( current->process );
- req->tid = get_thread_id( current );
- req->boot = (current == booting_thread);
- req->version = SERVER_PROTOCOL_VERSION;
+ reply->pid = get_process_id( current->process );
+ reply->tid = get_thread_id( current );
+ reply->boot = (current == booting_thread);
+ reply->version = SERVER_PROTOCOL_VERSION;
return;
error:
@@ -809,52 +815,21 @@
if (wait_fd != -1) close( wait_fd );
}
-/* set the shared buffer for a thread */
-DECL_HANDLER(set_thread_buffer)
-{
- const unsigned int size = MAX_REQUEST_LENGTH;
- const unsigned int offset = 0;
- int fd = thread_get_inflight_fd( current, req->fd );
-
- req->size = size;
- req->offset = offset;
-
- if (fd != -1)
- {
- static const char zero;
-
- /* grow the file to the requested size */
- if (lseek( fd, size - 1, SEEK_SET ) != -1 && write( fd, &zero, 1 ) == 1)
- {
- void *buffer = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset );
- if (buffer == (void *)-1) file_set_error();
- else
- {
- if (current->buffer != (void *)-1) munmap( current->buffer, size );
- current->buffer = buffer;
- }
- }
- else file_set_error();
- close( fd );
- }
- else set_error( STATUS_INVALID_HANDLE );
-}
-
/* terminate a thread */
DECL_HANDLER(terminate_thread)
{
struct thread *thread;
- req->self = 0;
- req->last = 0;
+ reply->self = 0;
+ reply->last = 0;
if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
{
thread->exit_code = req->exit_code;
if (thread != current) kill_thread( thread, 1 );
else
{
- req->self = 1;
- req->last = (thread->process->running_threads == 1);
+ reply->self = 1;
+ reply->last = (thread->process->running_threads == 1);
}
release_object( thread );
}
@@ -871,10 +846,10 @@
if (thread)
{
- req->tid = get_thread_id( thread );
- req->teb = thread->teb;
- req->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
- req->priority = thread->priority;
+ reply->tid = get_thread_id( thread );
+ reply->teb = thread->teb;
+ reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
+ reply->priority = thread->priority;
release_object( thread );
}
}
@@ -898,7 +873,7 @@
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
{
- req->count = suspend_thread( thread, 1 );
+ reply->count = suspend_thread( thread, 1 );
release_object( thread );
}
}
@@ -910,7 +885,7 @@
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
{
- req->count = resume_thread( thread );
+ reply->count = resume_thread( thread );
release_object( thread );
}
}
@@ -918,8 +893,8 @@
/* select on a handle list */
DECL_HANDLER(select)
{
- int count = get_req_data_size(req) / sizeof(int);
- select_on( count, req->cookie, get_req_data(req), req->flags, req->sec, req->usec );
+ int count = get_req_data_size() / sizeof(int);
+ select_on( count, req->cookie, get_req_data(), req->flags, req->sec, req->usec );
}
/* queue an APC for a thread */
@@ -944,9 +919,8 @@
if (!(apc = thread_dequeue_apc( current, !req->alertable )))
{
/* no more APCs */
- req->func = NULL;
- req->type = APC_NONE;
- set_req_data_size( req, 0 );
+ reply->func = NULL;
+ reply->type = APC_NONE;
return;
}
/* Optimization: ignore APCs that have a NULL func; they are only used
@@ -956,11 +930,10 @@
free( apc );
}
size = apc->nb_args * sizeof(apc->args[0]);
- if (size > get_req_data_size(req)) size = get_req_data_size(req);
- req->func = apc->func;
- req->type = apc->type;
- memcpy( get_req_data(req), apc->args, size );
- set_req_data_size( req, size );
+ if (size > get_reply_max_size()) size = get_reply_max_size();
+ reply->func = apc->func;
+ reply->type = apc->type;
+ set_reply_data( apc->args, size );
free( apc );
}
@@ -970,7 +943,7 @@
struct thread *thread;
if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
{
- get_selector_entry( thread, req->entry, &req->base, &req->limit, &req->flags );
+ get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
release_object( thread );
}
}