From 63411dbde5aa6faeee64cfab9af35c4a74b6dc4d Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 22 Dec 2000 21:12:36 +0000 Subject: [PATCH] Avoid dup'ing file descriptors when not necessary. Do not send fd to the client if ops->get_fd() fails. --- server/async.c | 2 +- server/console.c | 6 +++--- server/file.c | 11 ++++++++--- server/handle.c | 1 - server/mapping.c | 14 +++++++------- server/pipe.c | 2 +- server/registry.c | 4 ++-- server/request.c | 5 ++++- server/serial.c | 2 +- server/sock.c | 6 +----- server/thread.c | 3 +++ 11 files changed, 31 insertions(+), 25 deletions(-) diff --git a/server/async.c b/server/async.c index 7978a908995..fb722bc7468 100644 --- a/server/async.c +++ b/server/async.c @@ -117,7 +117,7 @@ static int async_get_fd( struct object *obj ) { struct async *async = (struct async *)obj; assert( obj->ops == &async_ops ); - return dup( async->obj.fd ); + return async->obj.fd; } static int async_get_info( struct object *obj, struct get_file_info_request *req ) { diff --git a/server/console.c b/server/console.c index dcdc28722eb..7454c9ac394 100644 --- a/server/console.c +++ b/server/console.c @@ -354,7 +354,7 @@ static int console_input_get_fd( struct object *obj ) { struct console_input *console = (struct console_input *)obj; assert( obj->ops == &console_input_ops ); - return dup( console->obj.fd ); + return console->obj.fd; } static int console_get_info( struct object *obj, struct get_file_info_request *req ) @@ -395,7 +395,7 @@ static int screen_buffer_get_fd( struct object *obj ) { struct screen_buffer *console = (struct screen_buffer *)obj; assert( obj->ops == &screen_buffer_ops ); - return dup( console->obj.fd ); + return console->obj.fd; } static void screen_buffer_destroy( struct object *obj ) @@ -481,7 +481,7 @@ DECL_HANDLER(set_console_fd) if (!(obj = get_handle_obj( current->process, req->file_handle, GENERIC_READ | GENERIC_WRITE, NULL ))) return; - if ((fd_in = obj->ops->get_fd( obj )) == -1) + if ((fd_in = dup(obj->ops->get_fd( obj ))) == -1) { release_object( obj ); return; diff --git a/server/file.c b/server/file.c index e0ce8a76285..0c8aaae3792 100644 --- a/server/file.c +++ b/server/file.c @@ -235,7 +235,7 @@ static int file_get_fd( struct object *obj ) { struct file *file = (struct file *)obj; assert( obj->ops == &file_ops ); - return dup( file->obj.fd ); + return file->obj.fd; } static int file_flush( struct object *obj ) @@ -474,8 +474,13 @@ DECL_HANDLER(get_handle_fd) req->fd = -1; if ((obj = get_handle_obj( current->process, req->handle, req->access, NULL ))) { - if ((req->fd = get_handle_fd( current->process, req->handle, req->access )) == -1) - send_client_fd( current, obj->ops->get_fd( obj ), req->handle ); + int fd = get_handle_fd( current->process, req->handle, req->access ); + if (fd != -1) req->fd = fd; + else if (!get_error()) + { + if ((fd = obj->ops->get_fd( obj )) != -1) + send_client_fd( current, fd, req->handle ); + } release_object( obj ); } } diff --git a/server/handle.c b/server/handle.c index 6a3e1f613c3..c3b8a05071a 100644 --- a/server/handle.c +++ b/server/handle.c @@ -362,7 +362,6 @@ int get_handle_fd( struct process *process, int handle, unsigned int access ) { struct handle_entry *entry; - if (HANDLE_IS_GLOBAL(handle)) return -1; /* no fd cache for global handles */ if (!(entry = get_handle( process, handle ))) return -1; if ((entry->access & access) != access) { diff --git a/server/mapping.c b/server/mapping.c index 38d1d899bef..43a67d8aaef 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -91,7 +91,11 @@ static void init_page_size(void) inline static int get_mmap_fd( struct file *file ) { struct object *obj; - if (!(obj = (struct object *)file)) return -1; + if (!(obj = (struct object *)file)) + { + set_error( STATUS_INVALID_HANDLE ); + return -1; + } return obj->ops->get_fd( obj ); } @@ -100,8 +104,8 @@ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, int nb_sec ) { int i, max_size, total_size, pos; - char *buffer = NULL; - int shared_fd = -1; + char *buffer = NULL; + int shared_fd; long toread; /* compute the total size of the shared mapping */ @@ -147,12 +151,10 @@ static int build_shared_mapping( struct mapping *mapping, int fd, } if (write( shared_fd, buffer, sec[i].SizeOfRawData ) != sec[i].SizeOfRawData) goto error; } - close( shared_fd ); free( buffer ); return 1; error: - if (shared_fd != -1) close( shared_fd ); if (buffer) free( buffer ); return 0; } @@ -193,13 +195,11 @@ static int get_image_params( struct mapping *mapping ) if (mapping->header_size > mapping->size_low) goto error; lseek( fd, filepos, SEEK_SET ); - close( fd ); free( sec ); return 1; error: lseek( fd, filepos, SEEK_SET ); - close( fd ); if (sec) free( sec ); set_error( STATUS_INVALID_FILE_FOR_SECTION ); return 0; diff --git a/server/pipe.c b/server/pipe.c index 7838c12caf5..47dfb61a1a2 100644 --- a/server/pipe.c +++ b/server/pipe.c @@ -122,7 +122,7 @@ static int pipe_get_fd( struct object *obj ) set_error( STATUS_PIPE_BROKEN ); return -1; } - return dup( pipe->obj.fd ); + return pipe->obj.fd; } static int pipe_get_info( struct object *obj, struct get_file_info_request *req ) diff --git a/server/registry.c b/server/registry.c index af7ba8a0510..4fa5a4ebf4c 100644 --- a/server/registry.c +++ b/server/registry.c @@ -1340,7 +1340,7 @@ static void load_registry( struct key *key, int handle ) int fd; if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL ))) return; - fd = obj->ops->get_fd( obj ); + fd = dup(obj->ops->get_fd( obj )); release_object( obj ); if (fd != -1) { @@ -1435,7 +1435,7 @@ static void save_registry( struct key *key, int handle ) return; } if (!(obj = get_handle_obj( current->process, handle, GENERIC_WRITE, NULL ))) return; - fd = obj->ops->get_fd( obj ); + fd = dup(obj->ops->get_fd( obj )); release_object( obj ); if (fd != -1) { diff --git a/server/request.c b/server/request.c index fff02dd4531..7a8498bbe19 100644 --- a/server/request.c +++ b/server/request.c @@ -259,6 +259,9 @@ int send_client_fd( struct thread *thread, int fd, int handle ) { int ret; + if (debug_level) + fprintf( stderr, "%08x: *fd* %d = %d\n", (unsigned int)thread, handle, fd ); + #ifdef HAVE_MSGHDR_ACCRIGHTS msghdr.msg_accrightslen = sizeof(fd); msghdr.msg_accrights = (void *)&fd; @@ -272,7 +275,6 @@ int send_client_fd( struct thread *thread, int fd, int handle ) myiovec.iov_len = sizeof(handle); ret = sendmsg( thread->obj.fd, &msghdr, 0 ); - close( fd ); if (ret > 0) return 0; if (errno == EPIPE) @@ -381,6 +383,7 @@ struct object *create_request_socket( struct thread *thread ) } sock->thread = thread; send_client_fd( thread, fd[1], -1 ); + close( fd[1] ); set_select_events( &sock->obj, POLLIN ); return &sock->obj; } diff --git a/server/serial.c b/server/serial.c index 7d30d4dc957..f32f8a3eb7d 100644 --- a/server/serial.c +++ b/server/serial.c @@ -154,7 +154,7 @@ static int serial_get_fd( struct object *obj ) { struct serial *serial = (struct serial *)obj; assert( obj->ops == &serial_ops ); - return dup( serial->obj.fd ); + return serial->obj.fd; } static int serial_get_info( struct object *obj, struct get_file_info_request *req ) diff --git a/server/sock.c b/server/sock.c index c5f41e4f0d5..ec7a0676d64 100644 --- a/server/sock.c +++ b/server/sock.c @@ -255,12 +255,8 @@ static int sock_get_poll_events( struct object *obj ) static int sock_get_fd( struct object *obj ) { struct sock *sock = (struct sock *)obj; - int fd; assert( obj->ops == &sock_ops ); - fd = dup( sock->obj.fd ); - if (fd==-1) - sock_set_error(); - return fd; + return sock->obj.fd; } static void sock_destroy( struct object *obj ) diff --git a/server/thread.c b/server/thread.c index 12e937716e1..272614068f4 100644 --- a/server/thread.c +++ b/server/thread.c @@ -109,6 +109,8 @@ static int alloc_client_buffer( struct thread *thread ) send_client_fd( thread, fd_pipe[0], -1 ); send_client_fd( thread, fd, -1 ); send_reply( thread ); + close( fd_pipe[0] ); + close( fd ); return 1; error: @@ -691,6 +693,7 @@ DECL_HANDLER(new_thread) THREAD_ALL_ACCESS, req->inherit )) != -1) { send_client_fd( current, sock[1], req->handle ); + close( sock[1] ); /* thread object will be released when the thread gets killed */ add_process_thread( current->process, thread ); return;