Module: wine Branch: master Commit: ba40a0db8a7bd05b2e6e2763041875bcbc5af1b8 URL: https://source.winehq.org/git/wine.git/?a=commit;h=ba40a0db8a7bd05b2e6e27630...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Aug 16 15:10:33 2018 +0200
server: Store named_pipe reference in pipe_end struct.
Allows pipe clients to access named_pipe object after server is closed without disconnecting.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
server/named_pipe.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/server/named_pipe.c b/server/named_pipe.c index 768567f..ab71f36 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -67,6 +67,7 @@ struct pipe_end struct fd *fd; /* pipe file descriptor */ unsigned int flags; /* pipe flags */ unsigned int state; /* pipe state */ + struct named_pipe *pipe; struct pipe_end *connection; /* the other end of the pipe */ process_id_t client_pid; /* process that created the client */ process_id_t server_pid; /* process that created the server */ @@ -416,14 +417,20 @@ static void pipe_end_destroy( struct pipe_end *pipe_end ) free_async_queue( &pipe_end->read_q ); free_async_queue( &pipe_end->write_q ); if (pipe_end->fd) release_object( pipe_end->fd ); + if (pipe_end->pipe) release_object( pipe_end->pipe ); }
static void pipe_server_destroy( struct object *obj) { struct pipe_server *server = (struct pipe_server *)obj; + struct named_pipe *pipe = server->pipe_end.pipe;
assert( obj->ops == &pipe_server_ops );
+ assert( pipe->instances ); + if (!--pipe->instances) unlink_named_object( &pipe->obj ); + list_remove( &server->entry ); + pipe_end_disconnect( &server->pipe_end, STATUS_PIPE_BROKEN );
pipe_end_destroy( &server->pipe_end ); @@ -433,11 +440,7 @@ static void pipe_server_destroy( struct object *obj) server->client = NULL; }
- assert( server->pipe->instances ); - server->pipe->instances--; - - list_remove( &server->entry ); - release_object( server->pipe ); + release_object( pipe ); }
static void pipe_client_destroy( struct object *obj) @@ -573,6 +576,12 @@ static void pipe_end_get_file_info( struct fd *fd, struct named_pipe *pipe, unsi }
name = get_object_name( &pipe->obj, &name_len ); + /* FIXME: We should be able to return on unlinked pipe */ + if (!name) + { + set_error( STATUS_PIPE_DISCONNECTED ); + return; + } reply_size = offsetof( FILE_NAME_INFORMATION, FileName[name_len/sizeof(WCHAR) + 1] ); if (reply_size > get_reply_max_size()) { @@ -1043,7 +1052,10 @@ static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *as case ps_connected_server: assert( server->client );
- /* dump the client and server fds - client loses all waiting data */ + /* dump the client connection - all data is lost */ + release_object( server->pipe_end.connection->pipe ); + server->pipe_end.connection->pipe = NULL; + pipe_end_disconnect( &server->pipe_end, STATUS_PIPE_DISCONNECTED ); server->client->server = NULL; server->client = NULL; @@ -1092,8 +1104,10 @@ static struct pipe_server *get_pipe_server_obj( struct process *process, return (struct pipe_server *) obj; }
-static void init_pipe_end( struct pipe_end *pipe_end, unsigned int pipe_flags, data_size_t buffer_size ) +static void init_pipe_end( struct pipe_end *pipe_end, struct named_pipe *pipe, + unsigned int pipe_flags, data_size_t buffer_size ) { + pipe_end->pipe = (struct named_pipe *)grab_object( pipe ); pipe_end->fd = NULL; pipe_end->flags = pipe_flags; pipe_end->connection = NULL; @@ -1115,7 +1129,7 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned server->pipe = pipe; server->client = NULL; server->options = options; - init_pipe_end( &server->pipe_end, pipe_flags, pipe->insize ); + init_pipe_end( &server->pipe_end, pipe, pipe_flags, pipe->insize ); server->pipe_end.state = FILE_PIPE_LISTENING_STATE; server->pipe_end.server_pid = get_process_id( current->process );
@@ -1132,7 +1146,7 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned return server; }
-static struct pipe_client *create_pipe_client( unsigned int flags, unsigned int pipe_flags, +static struct pipe_client *create_pipe_client( unsigned int flags, struct named_pipe *pipe, data_size_t buffer_size, unsigned int options ) { struct pipe_client *client; @@ -1143,7 +1157,7 @@ static struct pipe_client *create_pipe_client( unsigned int flags, unsigned int
client->server = NULL; client->flags = flags; - init_pipe_end( &client->pipe_end, pipe_flags, buffer_size ); + init_pipe_end( &client->pipe_end, pipe, pipe->flags, buffer_size ); client->pipe_end.state = FILE_PIPE_CONNECTED_STATE; client->pipe_end.client_pid = get_process_id( current->process );
@@ -1217,7 +1231,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc return NULL; }
- if ((client = create_pipe_client( options, pipe->flags, pipe->outsize, options ))) + if ((client = create_pipe_client( options, pipe, pipe->outsize, options ))) { if (server->state == ps_wait_open) fd_async_wake_up( server->pipe_end.fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );