Fixed refcount handling (waiting clients must not increase the

refcount of the pipe).
Converted linked lists to use the standard functions.
Small cleanups.
This commit is contained in:
Alexandre Julliard 2005-02-03 10:48:23 +00:00
parent 52e5ac5e41
commit 7c1cf8f009
1 changed files with 71 additions and 74 deletions

View File

@ -49,7 +49,6 @@
enum pipe_state enum pipe_state
{ {
ps_none,
ps_idle_server, ps_idle_server,
ps_wait_open, ps_wait_open,
ps_connected_server, ps_connected_server,
@ -69,13 +68,12 @@ struct named_pipe;
struct pipe_server struct pipe_server
{ {
struct object obj; struct object obj; /* object header */
struct fd *fd; struct fd *fd; /* pipe file descriptor */
enum pipe_state state; struct list entry; /* entry in named pipe servers list */
struct pipe_client *client; enum pipe_state state; /* server state */
struct pipe_client *client; /* client that this server is connected to */
struct named_pipe *pipe; struct named_pipe *pipe;
struct pipe_server *next;
struct pipe_server *prev;
struct timeout_user *flush_poll; struct timeout_user *flush_poll;
struct event *event; struct event *event;
struct wait_info wait; struct wait_info wait;
@ -83,16 +81,16 @@ struct pipe_server
struct pipe_client struct pipe_client
{ {
struct object obj; struct object obj; /* object header */
struct fd *fd; struct fd *fd; /* pipe file descriptor */
struct pipe_server *server; struct pipe_server *server; /* server that this client is connected to */
struct wait_info wait; struct wait_info wait;
}; };
struct connect_wait struct connect_wait
{ {
struct list entry; /* entry in named pipe wait list */
struct wait_info wait; struct wait_info wait;
struct connect_wait *next;
}; };
struct named_pipe struct named_pipe
@ -104,8 +102,8 @@ struct named_pipe
unsigned int insize; unsigned int insize;
unsigned int timeout; unsigned int timeout;
unsigned int instances; unsigned int instances;
struct pipe_server *servers; struct list servers; /* list of servers using this pipe */
struct connect_wait *connect_waiters; struct list waiters; /* list of clients waiting to connect */
}; };
static void named_pipe_dump( struct object *obj, int verbose ); static void named_pipe_dump( struct object *obj, int verbose );
@ -187,30 +185,23 @@ static void named_pipe_dump( struct object *obj, int verbose )
{ {
struct named_pipe *pipe = (struct named_pipe *) obj; struct named_pipe *pipe = (struct named_pipe *) obj;
assert( obj->ops == &named_pipe_ops ); assert( obj->ops == &named_pipe_ops );
fprintf( stderr, "named pipe %p\n" ,pipe); fprintf( stderr, "Named pipe " );
dump_object_name( &pipe->obj );
fprintf( stderr, "\n" );
} }
static void pipe_server_dump( struct object *obj, int verbose ) static void pipe_server_dump( struct object *obj, int verbose )
{ {
struct pipe_server *server = (struct pipe_server *) obj; struct pipe_server *server = (struct pipe_server *) obj;
assert( obj->ops == &pipe_server_ops ); assert( obj->ops == &pipe_server_ops );
fprintf( stderr, "named pipe server %p (state %d)\n", fprintf( stderr, "Named pipe server pipe=%p state=%d\n", server->pipe, server->state );
server, server->state );
} }
static void pipe_client_dump( struct object *obj, int verbose ) static void pipe_client_dump( struct object *obj, int verbose )
{ {
struct pipe_client *client = (struct pipe_client *) obj; struct pipe_client *client = (struct pipe_client *) obj;
assert( obj->ops == &pipe_server_ops ); assert( obj->ops == &pipe_client_ops );
fprintf( stderr, "named pipe client %p (server state %d)\n", fprintf( stderr, "Named pipe client server=%p\n", client->server );
client, client->server->state );
}
static void named_pipe_destroy( struct object *obj)
{
struct named_pipe *pipe = (struct named_pipe *) obj;
assert( !pipe->servers );
assert( !pipe->instances );
} }
static void notify_waiter( struct wait_info *wait, unsigned int status ) static void notify_waiter( struct wait_info *wait, unsigned int status )
@ -232,22 +223,29 @@ static void set_waiter( struct wait_info *wait, void *func, void *ov )
wait->overlapped = ov; wait->overlapped = ov;
} }
static void notify_connect_waiters( struct named_pipe *pipe ) static void notify_connect_waiters( struct named_pipe *pipe, unsigned int status )
{ {
struct connect_wait *cw, **x = &pipe->connect_waiters; struct list *ptr;
while( *x ) while ((ptr = list_head( &pipe->waiters )) != NULL)
{ {
cw = *x; struct connect_wait *waiter = LIST_ENTRY( ptr, struct connect_wait, entry );
notify_waiter( &cw->wait, STATUS_SUCCESS ); notify_waiter( &waiter->wait, status );
release_object( pipe ); list_remove( &waiter->entry );
*x = cw->next; free( waiter );
free( cw );
} }
} }
static void queue_connect_waiter( struct named_pipe *pipe, static void named_pipe_destroy( struct object *obj)
void *func, void *overlapped ) {
struct named_pipe *pipe = (struct named_pipe *) obj;
assert( list_empty( &pipe->servers ) );
assert( !pipe->instances );
notify_connect_waiters( pipe, STATUS_HANDLES_CLOSED );
}
static void queue_connect_waiter( struct named_pipe *pipe, void *func, void *overlapped )
{ {
struct connect_wait *waiter; struct connect_wait *waiter;
@ -255,9 +253,7 @@ static void queue_connect_waiter( struct named_pipe *pipe,
if( waiter ) if( waiter )
{ {
set_waiter( &waiter->wait, func, overlapped ); set_waiter( &waiter->wait, func, overlapped );
waiter->next = pipe->connect_waiters; list_add_tail( &pipe->waiters, &waiter->entry );
pipe->connect_waiters = waiter;
grab_object( pipe );
} }
} }
@ -290,9 +286,6 @@ static struct fd *pipe_server_get_fd( struct object *obj )
case ps_wait_connect: case ps_wait_connect:
set_error( STATUS_PIPE_DISCONNECTED ); set_error( STATUS_PIPE_DISCONNECTED );
break; break;
default:
assert( 0 );
} }
return NULL; return NULL;
} }
@ -349,10 +342,7 @@ static void pipe_server_destroy( struct object *obj)
assert( server->pipe->instances ); assert( server->pipe->instances );
server->pipe->instances--; server->pipe->instances--;
/* remove server from pipe's server list */ list_remove( &server->entry );
if( server->next ) server->next->prev = server->prev;
if( server->prev ) server->prev->next = server->next;
else server->pipe->servers = server->next;
release_object( server->pipe ); release_object( server->pipe );
} }
@ -381,7 +371,10 @@ static void pipe_client_destroy( struct object *obj)
case ps_disconnected_server: case ps_disconnected_server:
server->state = ps_wait_connect; server->state = ps_wait_connect;
break; break;
default: case ps_idle_server:
case ps_wait_open:
case ps_wait_disconnect:
case ps_wait_connect:
assert( 0 ); assert( 0 );
} }
assert( server->client ); assert( server->client );
@ -493,9 +486,9 @@ static struct named_pipe *create_named_pipe( const WCHAR *name, size_t len )
if( get_error() != STATUS_OBJECT_NAME_COLLISION ) if( get_error() != STATUS_OBJECT_NAME_COLLISION )
{ {
/* initialize it if it didn't already exist */ /* initialize it if it didn't already exist */
pipe->servers = 0;
pipe->instances = 0; pipe->instances = 0;
pipe->connect_waiters = NULL; list_init( &pipe->servers );
list_init( &pipe->waiters );
} }
} }
return pipe; return pipe;
@ -534,16 +527,12 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe )
server->fd = NULL; server->fd = NULL;
server->pipe = pipe; server->pipe = pipe;
server->state = ps_none; server->state = ps_idle_server;
server->client = NULL; server->client = NULL;
server->flush_poll = NULL; server->flush_poll = NULL;
server->wait.thread = NULL; server->wait.thread = NULL;
/* add to list of pipe servers */ list_add_head( &pipe->servers, &server->entry );
if ((server->next = pipe->servers)) server->next->prev = server;
server->prev = NULL;
pipe->servers = server;
grab_object( pipe ); grab_object( pipe );
return server; return server;
@ -564,19 +553,28 @@ static struct pipe_client *create_pipe_client( struct pipe_server *server )
return client; return client;
} }
static struct pipe_server *find_server( struct named_pipe *pipe, static inline struct pipe_server *find_server( struct named_pipe *pipe, enum pipe_state state )
enum pipe_state state )
{ {
struct pipe_server *x; struct pipe_server *server;
for( x = pipe->servers; x; x = x->next ) LIST_FOR_EACH_ENTRY( server, &pipe->servers, struct pipe_server, entry )
if( x->state == state ) {
break; if (server->state == state) return (struct pipe_server *)grab_object( server );
}
if( !x )
return NULL; return NULL;
}
return (struct pipe_server *) grab_object( x ); static inline struct pipe_server *find_server2( struct named_pipe *pipe,
enum pipe_state state1, enum pipe_state state2 )
{
struct pipe_server *server;
LIST_FOR_EACH_ENTRY( server, &pipe->servers, struct pipe_server, entry )
{
if (server->state == state1 || server->state == state2)
return (struct pipe_server *)grab_object( server );
}
return NULL;
} }
DECL_HANDLER(create_named_pipe) DECL_HANDLER(create_named_pipe)
@ -619,7 +617,6 @@ DECL_HANDLER(create_named_pipe)
server = create_pipe_server( pipe ); server = create_pipe_server( pipe );
if(server) if(server)
{ {
server->state = ps_idle_server;
reply->handle = alloc_handle( current->process, server, reply->handle = alloc_handle( current->process, server,
GENERIC_READ|GENERIC_WRITE, req->inherit ); GENERIC_READ|GENERIC_WRITE, req->inherit );
server->pipe->instances++; server->pipe->instances++;
@ -636,8 +633,6 @@ DECL_HANDLER(open_named_pipe)
struct named_pipe *pipe; struct named_pipe *pipe;
int fds[2]; int fds[2];
reply->handle = 0;
pipe = open_named_pipe( get_req_data(), get_req_data_size() ); pipe = open_named_pipe( get_req_data(), get_req_data_size() );
if ( !pipe ) if ( !pipe )
{ {
@ -645,10 +640,7 @@ DECL_HANDLER(open_named_pipe)
return; return;
} }
for( server = pipe->servers; server; server = server->next ) server = find_server2( pipe, ps_idle_server, ps_wait_open );
if( ( server->state==ps_idle_server ) ||
( server->state==ps_wait_open ) )
break;
release_object( pipe ); release_object( pipe );
if ( !server ) if ( !server )
@ -685,6 +677,7 @@ DECL_HANDLER(open_named_pipe)
release_object( client ); release_object( client );
} }
release_object( server );
} }
DECL_HANDLER(connect_named_pipe) DECL_HANDLER(connect_named_pipe)
@ -702,7 +695,7 @@ DECL_HANDLER(connect_named_pipe)
assert( !server->fd ); assert( !server->fd );
server->state = ps_wait_open; server->state = ps_wait_open;
set_waiter( &server->wait, req->func, req->overlapped ); set_waiter( &server->wait, req->func, req->overlapped );
notify_connect_waiters( server->pipe ); notify_connect_waiters( server->pipe, STATUS_SUCCESS );
break; break;
case ps_connected_server: case ps_connected_server:
assert( server->fd ); assert( server->fd );
@ -714,7 +707,7 @@ DECL_HANDLER(connect_named_pipe)
case ps_wait_disconnect: case ps_wait_disconnect:
set_error( STATUS_NO_DATA_DETECTED ); set_error( STATUS_NO_DATA_DETECTED );
break; break;
default: case ps_wait_open:
set_error( STATUS_INVALID_HANDLE ); set_error( STATUS_INVALID_HANDLE );
break; break;
} }
@ -780,8 +773,12 @@ DECL_HANDLER(disconnect_named_pipe)
reply->fd = flush_cached_fd( current->process, req->handle ); reply->fd = flush_cached_fd( current->process, req->handle );
break; break;
default: case ps_idle_server:
case ps_wait_open:
case ps_disconnected_server:
case ps_wait_connect:
set_error( STATUS_PIPE_DISCONNECTED ); set_error( STATUS_PIPE_DISCONNECTED );
break;
} }
release_object( server ); release_object( server );
} }