Added the data structures and macros that will be needed to support reentrant server requests.
diff --git a/server/request.c b/server/request.c index 3c619a4..9853e1e 100644 --- a/server/request.c +++ b/server/request.c
@@ -129,11 +129,14 @@ } /* call a request handler */ -static inline void call_req_handler( struct thread *thread, enum request req ) +static inline void call_req_handler( struct thread *thread ) { + enum request req; current = thread; clear_error(); + req = ((struct request_header *)current->buffer)->req; + if (debug_level) trace_request( req ); if (req < REQ_NB_REQUESTS) @@ -165,7 +168,7 @@ void read_request( struct thread *thread ) { int ret; - enum request req; + char dummy[1]; #ifdef HAVE_MSGHDR_ACCRIGHTS msghdr.msg_accrightslen = sizeof(int); @@ -178,43 +181,42 @@ assert( thread->pass_fd == -1 ); - myiovec.iov_base = (void *)&req; - myiovec.iov_len = sizeof(req); + myiovec.iov_base = dummy; + myiovec.iov_len = 1; ret = recvmsg( thread->obj.fd, &msghdr, 0 ); #ifndef HAVE_MSGHDR_ACCRIGHTS thread->pass_fd = cmsg.fd; #endif - if (ret == sizeof(req)) + if (ret > 0) { - call_req_handler( thread, req ); + call_req_handler( thread ); thread->pass_fd = -1; return; } - if (ret == -1) - { - perror("recvmsg"); - thread->exit_code = 1; - kill_thread( thread, 1 ); - return; - } if (!ret) /* closed pipe */ { kill_thread( thread, 0 ); return; } - fatal_protocol_error( thread, "partial message received %d/%d\n", ret, sizeof(req) ); + perror("recvmsg"); + thread->exit_code = 1; + kill_thread( thread, 1 ); } /* send a message to a client that is ready to receive something */ int write_request( struct thread *thread ) { int ret; + struct request_header *header = thread->buffer; + + header->error = thread->error; if (thread->pass_fd == -1) { - ret = write( thread->obj.fd, &thread->error, sizeof(thread->error) ); + /* write a single byte; the value is ignored anyway */ + ret = write( thread->obj.fd, header, 1 ); } else /* we have an fd to send */ { @@ -227,37 +229,28 @@ cmsg.fd = thread->pass_fd; #endif /* HAVE_MSGHDR_ACCRIGHTS */ - myiovec.iov_base = (void *)&thread->error; - myiovec.iov_len = sizeof(thread->error); + myiovec.iov_base = (void *)header; + myiovec.iov_len = 1; ret = sendmsg( thread->obj.fd, &msghdr, 0 ); close( thread->pass_fd ); thread->pass_fd = -1; } - if (ret == sizeof(thread->error)) + if (ret > 0) { set_select_events( &thread->obj, POLLIN ); return 1; } - if (ret == -1) + if (errno == EWOULDBLOCK) return 0; /* not a fatal error */ + if (errno == EPIPE) { - if (errno == EWOULDBLOCK) return 0; /* not a fatal error */ - if (errno == EPIPE) - { - kill_thread( thread, 0 ); /* normal death */ - } - else - { - perror("sendmsg"); - thread->exit_code = 1; - kill_thread( thread, 1 ); - } + kill_thread( thread, 0 ); /* normal death */ } else { + perror("sendmsg"); thread->exit_code = 1; kill_thread( thread, 1 ); - fprintf( stderr, "Partial message sent %d/%d\n", ret, sizeof(thread->error) ); } return -1; }
diff --git a/server/request.h b/server/request.h index 3ad0d33..aa46902 100644 --- a/server/request.h +++ b/server/request.h
@@ -48,17 +48,26 @@ return thread->buffer; } +/* get the request vararg data */ +inline static void *get_req_data( const void *req ) +{ + return ((union generic_request *)req + 1); +} + + +#define REQUEST_END(req) ((char *)(req) + MAX_REQUEST_LENGTH - sizeof(struct server_buffer_info)) + /* get the remaining size in the request buffer for object of a given size */ static inline int get_req_size( const void *req, const void *ptr, size_t typesize ) { - return ((char *)req + MAX_REQUEST_LENGTH - (char *)ptr) / typesize; + return (REQUEST_END(req) - (char *)ptr) / typesize; } /* get the length of a request string, without going past the end of the request */ static inline size_t get_req_strlen( const void *req, const char *str ) { const char *p = str; - while (*p && (p < (char *)req + MAX_REQUEST_LENGTH - 1)) p++; + while (*p && (p < REQUEST_END(req) - 1)) p++; return p - str; } @@ -66,7 +75,7 @@ static inline size_t get_req_strlenW( const void *req, const WCHAR *str ) { const WCHAR *p = str; - while (*p && (p < (WCHAR *)req + MAX_REQUEST_LENGTH/sizeof(WCHAR) - 1)) p++; + while (*p && (p < (WCHAR *)REQUEST_END(req) - 1)) p++; return p - str; }
diff --git a/server/thread.c b/server/thread.c index c00e61e..c1b79fa 100644 --- a/server/thread.c +++ b/server/thread.c
@@ -96,6 +96,7 @@ if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error; if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 )) == (void*)-1) goto error; + thread->buffer_info = (struct server_buffer_info *)((char *)thread->buffer + MAX_REQUEST_LENGTH) - 1; /* build the first request into the buffer and send it */ req = thread->buffer; req->pid = get_process_id( thread->process );
diff --git a/server/thread.h b/server/thread.h index 7c9ae9e..f0f170b 100644 --- a/server/thread.h +++ b/server/thread.h
@@ -59,6 +59,7 @@ int affinity; /* affinity mask */ int suspend; /* suspend count */ void *buffer; /* buffer for communication with the client */ + struct server_buffer_info *buffer_info; /* buffer information structure */ enum request last_req; /* last request received (for debugging) */ };
diff --git a/server/trace.c b/server/trace.c index 8774c81..34ff39c 100644 --- a/server/trace.c +++ b/server/trace.c
@@ -787,7 +787,6 @@ static void dump_free_console_request( const struct free_console_request *req ) { - fprintf( stderr, " dummy=%d", req->dummy ); } static void dump_open_console_request( const struct open_console_request *req )